Merge pull request #2708 from lambdageek/dev/monoerror-assorted-get_type
[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, MonoError *error);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
189
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
193
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
196
197 #define RESOLVE_TYPE(type, error) do {                                  \
198         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
199 } while (0)
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
201         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202         __type = mono_reflection_type_resolve_user_types (__type, error); \
203         if (mono_error_ok (error))                                      \
204                 mono_array_set (arr, MonoReflectionType*, index, __type); \
205 } while (0)
206
207 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
208
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
211
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
214 #else
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
216 #endif
217
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
220
221 /* Class lazy loading functions */
222 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
223 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
232 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
233 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
234 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
236 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
237 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
238 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
239 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
240 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
241
242 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
243 static GPtrArray *dynamic_images;
244 static mono_mutex_t dynamic_images_mutex;
245
246 static inline void
247 dynamic_images_lock (void)
248 {
249         mono_os_mutex_lock (&dynamic_images_mutex);
250 }
251
252 static inline void
253 dynamic_images_unlock (void)
254 {
255         mono_os_mutex_unlock (&dynamic_images_mutex);
256 }
257
258 /**
259  * mono_find_dynamic_image_owner:
260  *
261  * Find the dynamic image, if any, which a given pointer is located in the memory of.
262  */
263 MonoImage *
264 mono_find_dynamic_image_owner (void *ptr)
265 {
266         MonoImage *owner = NULL;
267         int i;
268
269         dynamic_images_lock ();
270
271         if (dynamic_images)
272         {
273                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
274                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
275                         if (mono_mempool_contains_addr (image->mempool, ptr))
276                                 owner = image;
277                 }
278         }
279
280         dynamic_images_unlock ();
281
282         return owner;
283 }
284
285 void
286 mono_reflection_init (void)
287 {
288         mono_os_mutex_init (&dynamic_images_mutex);
289 }
290
291 static inline void
292 dynamic_image_lock (MonoDynamicImage *image)
293 {
294         MONO_PREPARE_BLOCKING;
295         mono_image_lock ((MonoImage*)image);
296         MONO_FINISH_BLOCKING;
297 }
298
299 static inline void
300 dynamic_image_unlock (MonoDynamicImage *image)
301 {
302         mono_image_unlock ((MonoImage*)image);
303 }
304
305 static void
306 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
307 {
308         MONO_REQ_GC_UNSAFE_MODE;
309
310         dynamic_image_lock (assembly);
311         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
312         dynamic_image_unlock (assembly);
313 }
314
315 static MonoObject*
316 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
317 {
318         MONO_REQ_GC_UNSAFE_MODE;
319
320         MonoObject *obj;
321
322         dynamic_image_lock (assembly);
323         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
324         dynamic_image_unlock (assembly);
325
326         return obj;
327 }
328
329 static void
330 sigbuffer_init (SigBuffer *buf, int size)
331 {
332         MONO_REQ_GC_NEUTRAL_MODE;
333
334         buf->buf = (char *)g_malloc (size);
335         buf->p = buf->buf;
336         buf->end = buf->buf + size;
337 }
338
339 static void
340 sigbuffer_make_room (SigBuffer *buf, int size)
341 {
342         MONO_REQ_GC_NEUTRAL_MODE;
343
344         if (buf->end - buf->p < size) {
345                 int new_size = buf->end - buf->buf + size + 32;
346                 char *p = (char *)g_realloc (buf->buf, new_size);
347                 size = buf->p - buf->buf;
348                 buf->buf = p;
349                 buf->p = p + size;
350                 buf->end = buf->buf + new_size;
351         }
352 }
353
354 static void
355 sigbuffer_add_value (SigBuffer *buf, guint32 val)
356 {
357         MONO_REQ_GC_NEUTRAL_MODE;
358
359         sigbuffer_make_room (buf, 6);
360         mono_metadata_encode_value (val, buf->p, &buf->p);
361 }
362
363 static void
364 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
365 {
366         MONO_REQ_GC_NEUTRAL_MODE;
367
368         sigbuffer_make_room (buf, 1);
369         buf->p [0] = val;
370         buf->p++;
371 }
372
373 static void
374 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
375 {
376         MONO_REQ_GC_NEUTRAL_MODE;
377
378         sigbuffer_make_room (buf, size);
379         memcpy (buf->p, p, size);
380         buf->p += size;
381 }
382
383 static void
384 sigbuffer_free (SigBuffer *buf)
385 {
386         MONO_REQ_GC_NEUTRAL_MODE;
387
388         g_free (buf->buf);
389 }
390
391 #ifndef DISABLE_REFLECTION_EMIT
392 /**
393  * mp_g_alloc:
394  *
395  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396  * from the C heap.
397  */
398 static gpointer
399 image_g_malloc (MonoImage *image, guint size)
400 {
401         MONO_REQ_GC_NEUTRAL_MODE;
402
403         if (image)
404                 return mono_image_alloc (image, size);
405         else
406                 return g_malloc (size);
407 }
408 #endif /* !DISABLE_REFLECTION_EMIT */
409
410 /**
411  * image_g_alloc0:
412  *
413  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
414  * from the C heap.
415  */
416 static gpointer
417 image_g_malloc0 (MonoImage *image, guint size)
418 {
419         MONO_REQ_GC_NEUTRAL_MODE;
420
421         if (image)
422                 return mono_image_alloc0 (image, size);
423         else
424                 return g_malloc0 (size);
425 }
426
427 #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         MonoError error;
925
926         if (!type) {
927                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
928                 return;
929         }
930
931         MonoType *t = mono_reflection_type_get_handle (type, &error);
932         mono_error_raise_exception (&error); /* FIXME don't raise ehre */
933         encode_type (assembly, t, buf);
934 }
935
936 static void
937 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
938 {
939         MONO_REQ_GC_UNSAFE_MODE;
940
941         MonoError error;
942         int i;
943
944         if (modreq) {
945                 for (i = 0; i < mono_array_length (modreq); ++i) {
946                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, &error);
947                         mono_error_raise_exception (&error); /* FIXME don't raise here */
948                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
949                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
950                 }
951         }
952         if (modopt) {
953                 for (i = 0; i < mono_array_length (modopt); ++i) {
954                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, &error);
955                         mono_error_raise_exception (&error); /* FIXME don't raise here */
956                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
957                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
958                 }
959         }
960 }
961
962 #ifndef DISABLE_REFLECTION_EMIT
963 static guint32
964 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
965 {
966         MONO_REQ_GC_UNSAFE_MODE;
967
968         SigBuffer buf;
969         int i;
970         guint32 nparams =  sig->param_count;
971         guint32 idx;
972
973         if (!assembly->save)
974                 return 0;
975
976         sigbuffer_init (&buf, 32);
977         /*
978          * FIXME: vararg, explicit_this, differenc call_conv values...
979          */
980         idx = sig->call_convention;
981         if (sig->hasthis)
982                 idx |= 0x20; /* hasthis */
983         if (sig->generic_param_count)
984                 idx |= 0x10; /* generic */
985         sigbuffer_add_byte (&buf, idx);
986         if (sig->generic_param_count)
987                 sigbuffer_add_value (&buf, sig->generic_param_count);
988         sigbuffer_add_value (&buf, nparams);
989         encode_type (assembly, sig->ret, &buf);
990         for (i = 0; i < nparams; ++i) {
991                 if (i == sig->sentinelpos)
992                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
993                 encode_type (assembly, sig->params [i], &buf);
994         }
995         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
996         sigbuffer_free (&buf);
997         return idx;
998 }
999 #endif
1000
1001 static guint32
1002 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1003 {
1004         MONO_REQ_GC_UNSAFE_MODE;
1005
1006         /*
1007          * FIXME: reuse code from method_encode_signature().
1008          */
1009         SigBuffer buf;
1010         int i;
1011         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1012         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1013         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1014         guint32 idx;
1015
1016         sigbuffer_init (&buf, 32);
1017         /* LAMESPEC: all the call conv spec is foobared */
1018         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1019         if (mb->call_conv & 2)
1020                 idx |= 0x5; /* vararg */
1021         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1022                 idx |= 0x20; /* hasthis */
1023         if (ngparams)
1024                 idx |= 0x10; /* generic */
1025         sigbuffer_add_byte (&buf, idx);
1026         if (ngparams)
1027                 sigbuffer_add_value (&buf, ngparams);
1028         sigbuffer_add_value (&buf, nparams + notypes);
1029         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1030         encode_reflection_type (assembly, mb->rtype, &buf);
1031         for (i = 0; i < nparams; ++i) {
1032                 MonoArray *modreq = NULL;
1033                 MonoArray *modopt = NULL;
1034                 MonoReflectionType *pt;
1035
1036                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1037                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1038                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1039                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1040                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1041                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1042                 encode_reflection_type (assembly, pt, &buf);
1043         }
1044         if (notypes)
1045                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1046         for (i = 0; i < notypes; ++i) {
1047                 MonoReflectionType *pt;
1048
1049                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1050                 encode_reflection_type (assembly, pt, &buf);
1051         }
1052
1053         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1054         sigbuffer_free (&buf);
1055         return idx;
1056 }
1057
1058 static guint32
1059 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1060 {
1061         MONO_REQ_GC_UNSAFE_MODE;
1062
1063         MonoDynamicTable *table;
1064         guint32 *values;
1065         guint32 idx, sig_idx;
1066         guint nl = mono_array_length (ilgen->locals);
1067         SigBuffer buf;
1068         int i;
1069
1070         sigbuffer_init (&buf, 32);
1071         sigbuffer_add_value (&buf, 0x07);
1072         sigbuffer_add_value (&buf, nl);
1073         for (i = 0; i < nl; ++i) {
1074                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1075                 
1076                 if (lb->is_pinned)
1077                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1078                 
1079                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1080         }
1081         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1082         sigbuffer_free (&buf);
1083
1084         if (assembly->standalonesig_cache == NULL)
1085                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1086         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1087         if (idx)
1088                 return idx;
1089
1090         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1091         idx = table->next_idx ++;
1092         table->rows ++;
1093         alloc_table (table, table->rows);
1094         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1095
1096         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1097
1098         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1099
1100         return idx;
1101 }
1102
1103 static guint32
1104 method_count_clauses (MonoReflectionILGen *ilgen)
1105 {
1106         MONO_REQ_GC_UNSAFE_MODE;
1107
1108         guint32 num_clauses = 0;
1109         int i;
1110
1111         MonoILExceptionInfo *ex_info;
1112         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1113                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1114                 if (ex_info->handlers)
1115                         num_clauses += mono_array_length (ex_info->handlers);
1116                 else
1117                         num_clauses++;
1118         }
1119
1120         return num_clauses;
1121 }
1122
1123 #ifndef DISABLE_REFLECTION_EMIT
1124 static MonoExceptionClause*
1125 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1126 {
1127         MONO_REQ_GC_UNSAFE_MODE;
1128
1129         MonoError error;
1130         MonoExceptionClause *clauses;
1131         MonoExceptionClause *clause;
1132         MonoILExceptionInfo *ex_info;
1133         MonoILExceptionBlock *ex_block;
1134         guint32 finally_start;
1135         int i, j, clause_index;;
1136
1137         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1138
1139         clause_index = 0;
1140         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1141                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1142                 finally_start = ex_info->start + ex_info->len;
1143                 if (!ex_info->handlers)
1144                         continue;
1145                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1146                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1147                         clause = &(clauses [clause_index]);
1148
1149                         clause->flags = ex_block->type;
1150                         clause->try_offset = ex_info->start;
1151
1152                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1153                                 clause->try_len = finally_start - ex_info->start;
1154                         else
1155                                 clause->try_len = ex_info->len;
1156                         clause->handler_offset = ex_block->start;
1157                         clause->handler_len = ex_block->len;
1158                         if (ex_block->extype) {
1159                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, &error);
1160                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
1161                                 clause->data.catch_class = mono_class_from_mono_type (extype);
1162                         } else {
1163                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1164                                         clause->data.filter_offset = ex_block->filter_offset;
1165                                 else
1166                                         clause->data.filter_offset = 0;
1167                         }
1168                         finally_start = ex_block->start + ex_block->len;
1169
1170                         clause_index ++;
1171                 }
1172         }
1173
1174         return clauses;
1175 }
1176 #endif /* !DISABLE_REFLECTION_EMIT */
1177
1178 /**
1179  * method_encode_code:
1180  *
1181  * @assembly the assembly
1182  * @mb the managed MethodBuilder
1183  * @error set on error
1184  *
1185  * Note that the return value is not sensible if @error is set.
1186  */
1187 static guint32
1188 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1189 {
1190         MONO_REQ_GC_UNSAFE_MODE;
1191
1192         char flags = 0;
1193         guint32 idx;
1194         guint32 code_size;
1195         gint32 max_stack, i;
1196         gint32 num_locals = 0;
1197         gint32 num_exception = 0;
1198         gint maybe_small;
1199         guint32 fat_flags;
1200         char fat_header [12];
1201         guint32 int_value;
1202         guint16 short_value;
1203         guint32 local_sig = 0;
1204         guint32 header_size = 12;
1205         MonoArray *code;
1206
1207         mono_error_init (error);
1208
1209         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1210                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1211                 return 0;
1212
1213         /*if (mb->name)
1214                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1215         if (mb->ilgen) {
1216                 code = mb->ilgen->code;
1217                 code_size = mb->ilgen->code_len;
1218                 max_stack = mb->ilgen->max_stack;
1219                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1220                 if (mb->ilgen->ex_handlers)
1221                         num_exception = method_count_clauses (mb->ilgen);
1222         } else {
1223                 code = mb->code;
1224                 if (code == NULL){
1225                         char *name = mono_string_to_utf8 (mb->name);
1226                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1227                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1228                         g_free (str);
1229                         g_free (name);
1230                         return 0;
1231                 }
1232
1233                 code_size = mono_array_length (code);
1234                 max_stack = 8; /* we probably need to run a verifier on the code... */
1235         }
1236
1237         stream_data_align (&assembly->code);
1238
1239         /* check for exceptions, maxstack, locals */
1240         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1241         if (maybe_small) {
1242                 if (code_size < 64 && !(code_size & 1)) {
1243                         flags = (code_size << 2) | 0x2;
1244                 } else if (code_size < 32 && (code_size & 1)) {
1245                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1246                 } else {
1247                         goto fat_header;
1248                 }
1249                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1250                 /* add to the fixup todo list */
1251                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1252                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1253                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1254                 return assembly->text_rva + idx;
1255         } 
1256 fat_header:
1257         if (num_locals)
1258                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1259         /* 
1260          * FIXME: need to set also the header size in fat_flags.
1261          * (and more sects and init locals flags)
1262          */
1263         fat_flags =  0x03;
1264         if (num_exception)
1265                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1266         if (mb->init_locals)
1267                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1268         fat_header [0] = fat_flags;
1269         fat_header [1] = (header_size / 4 ) << 4;
1270         short_value = GUINT16_TO_LE (max_stack);
1271         memcpy (fat_header + 2, &short_value, 2);
1272         int_value = GUINT32_TO_LE (code_size);
1273         memcpy (fat_header + 4, &int_value, 4);
1274         int_value = GUINT32_TO_LE (local_sig);
1275         memcpy (fat_header + 8, &int_value, 4);
1276         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1277         /* add to the fixup todo list */
1278         if (mb->ilgen && mb->ilgen->num_token_fixups)
1279                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1280         
1281         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1282         if (num_exception) {
1283                 unsigned char sheader [4];
1284                 MonoILExceptionInfo * ex_info;
1285                 MonoILExceptionBlock * ex_block;
1286                 int j;
1287
1288                 stream_data_align (&assembly->code);
1289                 /* always use fat format for now */
1290                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1291                 num_exception *= 6 * sizeof (guint32);
1292                 num_exception += 4; /* include the size of the header */
1293                 sheader [1] = num_exception & 0xff;
1294                 sheader [2] = (num_exception >> 8) & 0xff;
1295                 sheader [3] = (num_exception >> 16) & 0xff;
1296                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1297                 /* fat header, so we are already aligned */
1298                 /* reverse order */
1299                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1300                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1301                         if (ex_info->handlers) {
1302                                 int finally_start = ex_info->start + ex_info->len;
1303                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1304                                         guint32 val;
1305                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1306                                         /* the flags */
1307                                         val = GUINT32_TO_LE (ex_block->type);
1308                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1309                                         /* try offset */
1310                                         val = GUINT32_TO_LE (ex_info->start);
1311                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1312                                         /* need fault, too, probably */
1313                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1314                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1315                                         else
1316                                                 val = GUINT32_TO_LE (ex_info->len);
1317                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1318                                         /* handler offset */
1319                                         val = GUINT32_TO_LE (ex_block->start);
1320                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1321                                         /* handler len */
1322                                         val = GUINT32_TO_LE (ex_block->len);
1323                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1324                                         finally_start = ex_block->start + ex_block->len;
1325                                         if (ex_block->extype) {
1326                                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1327                                                 return_val_if_nok (error, 0);
1328
1329                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1330                                         } else {
1331                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1332                                                         val = ex_block->filter_offset;
1333                                                 else
1334                                                         val = 0;
1335                                         }
1336                                         val = GUINT32_TO_LE (val);
1337                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1338                                         /*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", 
1339                                                         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);*/
1340                                 }
1341                         } else {
1342                                 g_error ("No clauses for ex info block %d", i);
1343                         }
1344                 }
1345         }
1346         return assembly->text_rva + idx;
1347 }
1348
1349 static guint32
1350 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1351 {
1352         MONO_REQ_GC_NEUTRAL_MODE;
1353
1354         int i;
1355         MonoDynamicTable *table;
1356         guint32 *values;
1357         
1358         table = &assembly->tables [table_idx];
1359
1360         g_assert (col < table->columns);
1361
1362         values = table->values + table->columns;
1363         for (i = 1; i <= table->rows; ++i) {
1364                 if (values [col] == token)
1365                         return i;
1366                 values += table->columns;
1367         }
1368         return 0;
1369 }
1370
1371 /*
1372  * LOCKING: Acquires the loader lock. 
1373  */
1374 static MonoCustomAttrInfo*
1375 lookup_custom_attr (MonoImage *image, gpointer member)
1376 {
1377         MONO_REQ_GC_NEUTRAL_MODE;
1378
1379         MonoCustomAttrInfo* res;
1380
1381         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1382
1383         if (!res)
1384                 return NULL;
1385
1386         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1387         res->cached = 0;
1388         return res;
1389 }
1390
1391 static gboolean
1392 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1393 {
1394         MONO_REQ_GC_UNSAFE_MODE;
1395
1396         /* FIXME: Need to do more checks */
1397         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1398                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1399
1400                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1401                         return FALSE;
1402         }
1403
1404         return TRUE;
1405 }
1406
1407 static MonoCustomAttrInfo*
1408 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1409 {
1410         MONO_REQ_GC_UNSAFE_MODE;
1411
1412         int i, index, count, not_visible;
1413         MonoCustomAttrInfo *ainfo;
1414         MonoReflectionCustomAttr *cattr;
1415
1416         if (!cattrs)
1417                 return NULL;
1418         /* FIXME: check in assembly the Run flag is set */
1419
1420         count = mono_array_length (cattrs);
1421
1422         /* Skip nonpublic attributes since MS.NET seems to do the same */
1423         /* FIXME: This needs to be done more globally */
1424         not_visible = 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                         not_visible ++;
1429         }
1430         count -= not_visible;
1431
1432         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1433
1434         ainfo->image = image;
1435         ainfo->num_attrs = count;
1436         ainfo->cached = alloc_img != NULL;
1437         index = 0;
1438         for (i = 0; i < count; ++i) {
1439                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1440                 if (custom_attr_visible (image, cattr)) {
1441                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1442                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1443                         ainfo->attrs [index].ctor = cattr->ctor->method;
1444                         ainfo->attrs [index].data = saved;
1445                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1446                         index ++;
1447                 }
1448         }
1449
1450         return ainfo;
1451 }
1452
1453 #ifndef DISABLE_REFLECTION_EMIT
1454 /*
1455  * LOCKING: Acquires the loader lock. 
1456  */
1457 static void
1458 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1459 {
1460         MONO_REQ_GC_UNSAFE_MODE;
1461
1462         MonoCustomAttrInfo *ainfo, *tmp;
1463
1464         if (!cattrs || !mono_array_length (cattrs))
1465                 return;
1466
1467         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1468
1469         mono_loader_lock ();
1470         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1471         if (tmp)
1472                 mono_custom_attrs_free (tmp);
1473         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1474         mono_loader_unlock ();
1475
1476 }
1477 #endif
1478
1479 void
1480 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1481 {
1482         MONO_REQ_GC_NEUTRAL_MODE;
1483
1484         if (ainfo && !ainfo->cached)
1485                 g_free (ainfo);
1486 }
1487
1488 /*
1489  * idx is the table index of the object
1490  * type is one of MONO_CUSTOM_ATTR_*
1491  */
1492 static gboolean
1493 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1494 {
1495         MONO_REQ_GC_UNSAFE_MODE;
1496
1497         MonoDynamicTable *table;
1498         MonoReflectionCustomAttr *cattr;
1499         guint32 *values;
1500         guint32 count, i, token;
1501         char blob_size [6];
1502         char *p = blob_size;
1503         
1504         mono_error_init (error);
1505
1506         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1507         if (!cattrs)
1508                 return TRUE;
1509         count = mono_array_length (cattrs);
1510         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1511         table->rows += count;
1512         alloc_table (table, table->rows);
1513         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1514         idx <<= MONO_CUSTOM_ATTR_BITS;
1515         idx |= type;
1516         for (i = 0; i < count; ++i) {
1517                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1518                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1519                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1520                 if (!mono_error_ok (error)) goto fail;
1521                 type = mono_metadata_token_index (token);
1522                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1523                 switch (mono_metadata_token_table (token)) {
1524                 case MONO_TABLE_METHOD:
1525                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1526                         /*
1527                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1528                          * method, not the one returned by mono_image_create_token ().
1529                          */
1530                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1531                         break;
1532                 case MONO_TABLE_MEMBERREF:
1533                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1534                         break;
1535                 default:
1536                         g_warning ("got wrong token in custom attr");
1537                         continue;
1538                 }
1539                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1540                 p = blob_size;
1541                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1542                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1543                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1544                 values += MONO_CUSTOM_ATTR_SIZE;
1545                 ++table->next_idx;
1546         }
1547
1548         return TRUE;
1549
1550 fail:
1551         return FALSE;
1552 }
1553
1554 static void
1555 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1556 {
1557         MONO_REQ_GC_UNSAFE_MODE;
1558
1559         MonoDynamicTable *table;
1560         guint32 *values;
1561         guint32 count, i, idx;
1562         MonoReflectionPermissionSet *perm;
1563
1564         if (!permissions)
1565                 return;
1566
1567         count = mono_array_length (permissions);
1568         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1569         table->rows += count;
1570         alloc_table (table, table->rows);
1571
1572         for (i = 0; i < mono_array_length (permissions); ++i) {
1573                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1574
1575                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1576
1577                 idx = mono_metadata_token_index (parent_token);
1578                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1579                 switch (mono_metadata_token_table (parent_token)) {
1580                 case MONO_TABLE_TYPEDEF:
1581                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1582                         break;
1583                 case MONO_TABLE_METHOD:
1584                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1585                         break;
1586                 case MONO_TABLE_ASSEMBLY:
1587                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1588                         break;
1589                 default:
1590                         g_assert_not_reached ();
1591                 }
1592
1593                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1594                 values [MONO_DECL_SECURITY_PARENT] = idx;
1595                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1596
1597                 ++table->next_idx;
1598         }
1599 }
1600
1601 /*
1602  * Fill in the MethodDef and ParamDef tables for a method.
1603  * This is used for both normal methods and constructors.
1604  */
1605 static gboolean
1606 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1607 {
1608         MONO_REQ_GC_UNSAFE_MODE;
1609
1610         MonoDynamicTable *table;
1611         guint32 *values;
1612         guint i, count;
1613
1614         mono_error_init (error);
1615
1616         /* room in this table is already allocated */
1617         table = &assembly->tables [MONO_TABLE_METHOD];
1618         *mb->table_idx = table->next_idx ++;
1619         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1620         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1621         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1622         values [MONO_METHOD_FLAGS] = mb->attrs;
1623         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1624         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1625         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1626         if (!mono_error_ok (error))
1627                 return FALSE;
1628
1629         table = &assembly->tables [MONO_TABLE_PARAM];
1630         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1631
1632         mono_image_add_decl_security (assembly, 
1633                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1634
1635         if (mb->pinfo) {
1636                 MonoDynamicTable *mtable;
1637                 guint32 *mvalues;
1638                 
1639                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1640                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1641                 
1642                 count = 0;
1643                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1644                         if (mono_array_get (mb->pinfo, gpointer, i))
1645                                 count++;
1646                 }
1647                 table->rows += count;
1648                 alloc_table (table, table->rows);
1649                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1650                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1651                         MonoReflectionParamBuilder *pb;
1652                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1653                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1654                                 values [MONO_PARAM_SEQUENCE] = i;
1655                                 if (pb->name != NULL) {
1656                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1657                                 } else {
1658                                         values [MONO_PARAM_NAME] = 0;
1659                                 }
1660                                 values += MONO_PARAM_SIZE;
1661                                 if (pb->marshal_info) {
1662                                         mtable->rows++;
1663                                         alloc_table (mtable, mtable->rows);
1664                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1665                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1666                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1667                                 }
1668                                 pb->table_idx = table->next_idx++;
1669                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1670                                         guint32 field_type = 0;
1671                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1672                                         mtable->rows ++;
1673                                         alloc_table (mtable, mtable->rows);
1674                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1675                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1676                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1677                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1678                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1679                                 }
1680                         }
1681                 }
1682         }
1683
1684         return TRUE;
1685 }
1686
1687 #ifndef DISABLE_REFLECTION_EMIT
1688 static gboolean
1689 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1690 {
1691         MONO_REQ_GC_UNSAFE_MODE;
1692
1693         mono_error_init (error);
1694         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1695
1696         rmb->ilgen = mb->ilgen;
1697         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1698         return_val_if_nok (error, FALSE);
1699         rmb->parameters = mb->parameters;
1700         rmb->generic_params = mb->generic_params;
1701         rmb->generic_container = mb->generic_container;
1702         rmb->opt_types = NULL;
1703         rmb->pinfo = mb->pinfo;
1704         rmb->attrs = mb->attrs;
1705         rmb->iattrs = mb->iattrs;
1706         rmb->call_conv = mb->call_conv;
1707         rmb->code = mb->code;
1708         rmb->type = mb->type;
1709         rmb->name = mb->name;
1710         rmb->table_idx = &mb->table_idx;
1711         rmb->init_locals = mb->init_locals;
1712         rmb->skip_visibility = FALSE;
1713         rmb->return_modreq = mb->return_modreq;
1714         rmb->return_modopt = mb->return_modopt;
1715         rmb->param_modreq = mb->param_modreq;
1716         rmb->param_modopt = mb->param_modopt;
1717         rmb->permissions = mb->permissions;
1718         rmb->mhandle = mb->mhandle;
1719         rmb->nrefs = 0;
1720         rmb->refs = NULL;
1721
1722         if (mb->dll) {
1723                 rmb->charset = mb->charset;
1724                 rmb->extra_flags = mb->extra_flags;
1725                 rmb->native_cc = mb->native_cc;
1726                 rmb->dllentry = mb->dllentry;
1727                 rmb->dll = mb->dll;
1728         }
1729
1730         return TRUE;
1731 }
1732
1733 static gboolean
1734 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1735 {
1736         MONO_REQ_GC_UNSAFE_MODE;
1737
1738         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1739
1740         mono_error_init (error);
1741
1742         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1743
1744         rmb->ilgen = mb->ilgen;
1745         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1746         return_val_if_nok (error, FALSE);
1747         rmb->parameters = mb->parameters;
1748         rmb->generic_params = NULL;
1749         rmb->generic_container = NULL;
1750         rmb->opt_types = NULL;
1751         rmb->pinfo = mb->pinfo;
1752         rmb->attrs = mb->attrs;
1753         rmb->iattrs = mb->iattrs;
1754         rmb->call_conv = mb->call_conv;
1755         rmb->code = NULL;
1756         rmb->type = mb->type;
1757         rmb->name = mono_string_new (mono_domain_get (), name);
1758         rmb->table_idx = &mb->table_idx;
1759         rmb->init_locals = mb->init_locals;
1760         rmb->skip_visibility = FALSE;
1761         rmb->return_modreq = NULL;
1762         rmb->return_modopt = NULL;
1763         rmb->param_modreq = mb->param_modreq;
1764         rmb->param_modopt = mb->param_modopt;
1765         rmb->permissions = mb->permissions;
1766         rmb->mhandle = mb->mhandle;
1767         rmb->nrefs = 0;
1768         rmb->refs = NULL;
1769
1770         return TRUE;
1771 }
1772
1773 static void
1774 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1775 {
1776         MONO_REQ_GC_UNSAFE_MODE;
1777
1778         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1779
1780         rmb->ilgen = mb->ilgen;
1781         rmb->rtype = mb->rtype;
1782         rmb->parameters = mb->parameters;
1783         rmb->generic_params = NULL;
1784         rmb->generic_container = NULL;
1785         rmb->opt_types = NULL;
1786         rmb->pinfo = NULL;
1787         rmb->attrs = mb->attrs;
1788         rmb->iattrs = 0;
1789         rmb->call_conv = mb->call_conv;
1790         rmb->code = NULL;
1791         rmb->type = (MonoObject *) mb->owner;
1792         rmb->name = mb->name;
1793         rmb->table_idx = NULL;
1794         rmb->init_locals = mb->init_locals;
1795         rmb->skip_visibility = mb->skip_visibility;
1796         rmb->return_modreq = NULL;
1797         rmb->return_modopt = NULL;
1798         rmb->param_modreq = NULL;
1799         rmb->param_modopt = NULL;
1800         rmb->permissions = NULL;
1801         rmb->mhandle = mb->mhandle;
1802         rmb->nrefs = 0;
1803         rmb->refs = NULL;
1804 }       
1805 #endif
1806
1807 static gboolean
1808 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1809 {
1810         MONO_REQ_GC_UNSAFE_MODE;
1811
1812         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1813         MonoDynamicTable *table;
1814         guint32 *values;
1815         guint32 tok;
1816         MonoReflectionMethod *m;
1817         int i;
1818
1819         mono_error_init (error);
1820
1821         if (!mb->override_methods)
1822                 return TRUE;
1823
1824         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1825                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1826
1827                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1828                 table->rows ++;
1829                 alloc_table (table, table->rows);
1830                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1831                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1832                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1833
1834                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1835                 return_val_if_nok (error, FALSE);
1836
1837                 switch (mono_metadata_token_table (tok)) {
1838                 case MONO_TABLE_MEMBERREF:
1839                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1840                         break;
1841                 case MONO_TABLE_METHOD:
1842                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1843                         break;
1844                 default:
1845                         g_assert_not_reached ();
1846                 }
1847                 values [MONO_METHODIMPL_DECLARATION] = tok;
1848         }
1849
1850         return TRUE;
1851 }
1852
1853 #ifndef DISABLE_REFLECTION_EMIT
1854 static gboolean
1855 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1856 {
1857         MONO_REQ_GC_UNSAFE_MODE;
1858
1859         MonoDynamicTable *table;
1860         guint32 *values;
1861         ReflectionMethodBuilder rmb;
1862         int i;
1863
1864         mono_error_init (error);
1865
1866         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1867             !mono_image_basic_method (&rmb, assembly, error))
1868                 return FALSE;
1869
1870         mb->table_idx = *rmb.table_idx;
1871
1872         if (mb->dll) { /* It's a P/Invoke method */
1873                 guint32 moduleref;
1874                 /* map CharSet values to on-disk values */
1875                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1876                 int extra_flags = mb->extra_flags;
1877                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1878                 table->rows ++;
1879                 alloc_table (table, table->rows);
1880                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1881                 
1882                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1883                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1884                 if (mb->dllentry)
1885                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1886                 else
1887                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1888                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1889                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1890                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1891                         table->rows ++;
1892                         alloc_table (table, table->rows);
1893                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1894                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1895                 }
1896         }
1897
1898         if (mb->generic_params) {
1899                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1900                 table->rows += mono_array_length (mb->generic_params);
1901                 alloc_table (table, table->rows);
1902                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1903                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1904
1905                         mono_image_get_generic_param_info (
1906                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1907                 }
1908         }
1909
1910         return TRUE;
1911 }
1912
1913 static gboolean
1914 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1915 {
1916         MONO_REQ_GC_UNSAFE_MODE;
1917
1918         ReflectionMethodBuilder rmb;
1919
1920         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1921                 return FALSE;
1922
1923         if (!mono_image_basic_method (&rmb, assembly, error))
1924                 return FALSE;
1925
1926         mb->table_idx = *rmb.table_idx;
1927
1928         return TRUE;
1929 }
1930 #endif
1931
1932 static char*
1933 type_get_fully_qualified_name (MonoType *type)
1934 {
1935         MONO_REQ_GC_NEUTRAL_MODE;
1936
1937         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1938 }
1939
1940 static char*
1941 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1942 {
1943         MONO_REQ_GC_UNSAFE_MODE;
1944
1945         MonoClass *klass;
1946         MonoAssembly *ta;
1947
1948         klass = mono_class_from_mono_type (type);
1949         if (!klass) 
1950                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1951         ta = klass->image->assembly;
1952         if (assembly_is_dynamic (ta) || (ta == ass)) {
1953                 if (klass->generic_class || klass->generic_container)
1954                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1955                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1956                 else
1957                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1958         }
1959
1960         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1961 }
1962
1963 #ifndef DISABLE_REFLECTION_EMIT
1964 /*field_image is the image to which the eventual custom mods have been encoded against*/
1965 static guint32
1966 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1967 {
1968         MONO_REQ_GC_NEUTRAL_MODE;
1969
1970         SigBuffer buf;
1971         guint32 idx, i, token;
1972
1973         if (!assembly->save)
1974                 return 0;
1975
1976         sigbuffer_init (&buf, 32);
1977         
1978         sigbuffer_add_value (&buf, 0x06);
1979         /* encode custom attributes before the type */
1980         if (type->num_mods) {
1981                 for (i = 0; i < type->num_mods; ++i) {
1982                         if (field_image) {
1983                                 MonoError error;
1984                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1985                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1986
1987                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1988                         } else {
1989                                 token = type->modifiers [i].token;
1990                         }
1991
1992                         if (type->modifiers [i].required)
1993                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1994                         else
1995                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1996
1997                         sigbuffer_add_value (&buf, token);
1998                 }
1999         }
2000         encode_type (assembly, type, &buf);
2001         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2002         sigbuffer_free (&buf);
2003         return idx;
2004 }
2005 #endif
2006
2007 static guint32
2008 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2009 {
2010         MONO_REQ_GC_UNSAFE_MODE;
2011
2012         MonoError error;
2013         SigBuffer buf;
2014         guint32 idx;
2015         guint32 typespec = 0;
2016         MonoType *type;
2017         MonoClass *klass;
2018
2019         init_type_builder_generics (fb->type);
2020
2021         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
2022         mono_error_raise_exception (&error); /* FIXME don't raise here */
2023         klass = mono_class_from_mono_type (type);
2024
2025         sigbuffer_init (&buf, 32);
2026         
2027         sigbuffer_add_value (&buf, 0x06);
2028         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
2029         /* encode custom attributes before the type */
2030
2031         if (klass->generic_container)
2032                 typespec = create_typespec (assembly, type);
2033
2034         if (typespec) {
2035                 MonoGenericClass *gclass;
2036                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2037                 encode_generic_class (assembly, gclass, &buf);
2038         } else {
2039                 encode_type (assembly, type, &buf);
2040         }
2041         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2042         sigbuffer_free (&buf);
2043         return idx;
2044 }
2045
2046 static guint32
2047 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2048 {
2049         MONO_REQ_GC_UNSAFE_MODE;
2050
2051         char blob_size [64];
2052         char *b = blob_size;
2053         char *box_val;
2054         char* buf;
2055         guint32 idx = 0, len = 0, dummy = 0;
2056
2057         buf = (char *)g_malloc (64);
2058         if (!val) {
2059                 *ret_type = MONO_TYPE_CLASS;
2060                 len = 4;
2061                 box_val = (char*)&dummy;
2062         } else {
2063                 box_val = ((char*)val) + sizeof (MonoObject);
2064                 *ret_type = val->vtable->klass->byval_arg.type;
2065         }
2066 handle_enum:
2067         switch (*ret_type) {
2068         case MONO_TYPE_BOOLEAN:
2069         case MONO_TYPE_U1:
2070         case MONO_TYPE_I1:
2071                 len = 1;
2072                 break;
2073         case MONO_TYPE_CHAR:
2074         case MONO_TYPE_U2:
2075         case MONO_TYPE_I2:
2076                 len = 2;
2077                 break;
2078         case MONO_TYPE_U4:
2079         case MONO_TYPE_I4:
2080         case MONO_TYPE_R4:
2081                 len = 4;
2082                 break;
2083         case MONO_TYPE_U8:
2084         case MONO_TYPE_I8:
2085                 len = 8;
2086                 break;
2087         case MONO_TYPE_R8:
2088                 len = 8;
2089                 break;
2090         case MONO_TYPE_VALUETYPE: {
2091                 MonoClass *klass = val->vtable->klass;
2092                 
2093                 if (klass->enumtype) {
2094                         *ret_type = mono_class_enum_basetype (klass)->type;
2095                         goto handle_enum;
2096                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2097                         len = 8;
2098                 } else 
2099                         g_error ("we can't encode valuetypes, we should have never reached this line");
2100                 break;
2101         }
2102         case MONO_TYPE_CLASS:
2103                 break;
2104         case MONO_TYPE_STRING: {
2105                 MonoString *str = (MonoString*)val;
2106                 /* there is no signature */
2107                 len = str->length * 2;
2108                 mono_metadata_encode_value (len, b, &b);
2109 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2110                 {
2111                         char *swapped = g_malloc (2 * mono_string_length (str));
2112                         const char *p = (const char*)mono_string_chars (str);
2113
2114                         swap_with_size (swapped, p, 2, mono_string_length (str));
2115                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2116                         g_free (swapped);
2117                 }
2118 #else
2119                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2120 #endif
2121
2122                 g_free (buf);
2123                 return idx;
2124         }
2125         case MONO_TYPE_GENERICINST:
2126                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2127                 goto handle_enum;
2128         default:
2129                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2130         }
2131
2132         /* there is no signature */
2133         mono_metadata_encode_value (len, b, &b);
2134 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2135         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2136         swap_with_size (blob_size, box_val, len, 1);
2137         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2138 #else
2139         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2140 #endif
2141
2142         g_free (buf);
2143         return idx;
2144 }
2145
2146 static guint32
2147 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2148 {
2149         MONO_REQ_GC_UNSAFE_MODE;
2150
2151         MonoError error;
2152         char *str;
2153         SigBuffer buf;
2154         guint32 idx, len;
2155
2156         sigbuffer_init (&buf, 32);
2157
2158         sigbuffer_add_value (&buf, minfo->type);
2159
2160         switch (minfo->type) {
2161         case MONO_NATIVE_BYVALTSTR:
2162         case MONO_NATIVE_BYVALARRAY:
2163                 sigbuffer_add_value (&buf, minfo->count);
2164                 break;
2165         case MONO_NATIVE_LPARRAY:
2166                 if (minfo->eltype || minfo->has_size) {
2167                         sigbuffer_add_value (&buf, minfo->eltype);
2168                         if (minfo->has_size) {
2169                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2170                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2171
2172                                 /* LAMESPEC: ElemMult is undocumented */
2173                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2174                         }
2175                 }
2176                 break;
2177         case MONO_NATIVE_SAFEARRAY:
2178                 if (minfo->eltype)
2179                         sigbuffer_add_value (&buf, minfo->eltype);
2180                 break;
2181         case MONO_NATIVE_CUSTOM:
2182                 if (minfo->guid) {
2183                         str = mono_string_to_utf8 (minfo->guid);
2184                         len = strlen (str);
2185                         sigbuffer_add_value (&buf, len);
2186                         sigbuffer_add_mem (&buf, str, len);
2187                         g_free (str);
2188                 } else {
2189                         sigbuffer_add_value (&buf, 0);
2190                 }
2191                 /* native type name */
2192                 sigbuffer_add_value (&buf, 0);
2193                 /* custom marshaler type name */
2194                 if (minfo->marshaltype || minfo->marshaltyperef) {
2195                         if (minfo->marshaltyperef) {
2196                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
2197                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
2198                                 str = type_get_fully_qualified_name (marshaltype);
2199                         } else
2200                                 str = mono_string_to_utf8 (minfo->marshaltype);
2201                         len = strlen (str);
2202                         sigbuffer_add_value (&buf, len);
2203                         sigbuffer_add_mem (&buf, str, len);
2204                         g_free (str);
2205                 } else {
2206                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2207                         sigbuffer_add_value (&buf, 0);
2208                 }
2209                 if (minfo->mcookie) {
2210                         str = mono_string_to_utf8 (minfo->mcookie);
2211                         len = strlen (str);
2212                         sigbuffer_add_value (&buf, len);
2213                         sigbuffer_add_mem (&buf, str, len);
2214                         g_free (str);
2215                 } else {
2216                         sigbuffer_add_value (&buf, 0);
2217                 }
2218                 break;
2219         default:
2220                 break;
2221         }
2222         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2223         sigbuffer_free (&buf);
2224         return idx;
2225 }
2226
2227 static void
2228 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2229 {
2230         MONO_REQ_GC_UNSAFE_MODE;
2231
2232         MonoDynamicTable *table;
2233         guint32 *values;
2234
2235         /* maybe this fixup should be done in the C# code */
2236         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2237                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2238         table = &assembly->tables [MONO_TABLE_FIELD];
2239         fb->table_idx = table->next_idx ++;
2240         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2241         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2242         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2243         values [MONO_FIELD_FLAGS] = fb->attrs;
2244         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2245
2246         if (fb->offset != -1) {
2247                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2248                 table->rows ++;
2249                 alloc_table (table, table->rows);
2250                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2251                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2252                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2253         }
2254         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2255                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2256                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2257                 table->rows ++;
2258                 alloc_table (table, table->rows);
2259                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2260                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2261                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2262                 values [MONO_CONSTANT_TYPE] = field_type;
2263                 values [MONO_CONSTANT_PADDING] = 0;
2264         }
2265         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2266                 guint32 rva_idx;
2267                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2268                 table->rows ++;
2269                 alloc_table (table, table->rows);
2270                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2271                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2272                 /*
2273                  * We store it in the code section because it's simpler for now.
2274                  */
2275                 if (fb->rva_data) {
2276                         if (mono_array_length (fb->rva_data) >= 10)
2277                                 stream_data_align (&assembly->code);
2278                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2279                 } else
2280                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2281                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2282         }
2283         if (fb->marshal_info) {
2284                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2285                 table->rows ++;
2286                 alloc_table (table, table->rows);
2287                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2288                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2289                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2290         }
2291 }
2292
2293 static guint32
2294 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2295 {
2296         MONO_REQ_GC_UNSAFE_MODE;
2297
2298         SigBuffer buf;
2299         guint32 nparams = 0;
2300         MonoReflectionMethodBuilder *mb = fb->get_method;
2301         MonoReflectionMethodBuilder *smb = fb->set_method;
2302         guint32 idx, i;
2303
2304         if (mb && mb->parameters)
2305                 nparams = mono_array_length (mb->parameters);
2306         if (!mb && smb && smb->parameters)
2307                 nparams = mono_array_length (smb->parameters) - 1;
2308         sigbuffer_init (&buf, 32);
2309         if (fb->call_conv & 0x20)
2310                 sigbuffer_add_byte (&buf, 0x28);
2311         else
2312                 sigbuffer_add_byte (&buf, 0x08);
2313         sigbuffer_add_value (&buf, nparams);
2314         if (mb) {
2315                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2316                 for (i = 0; i < nparams; ++i) {
2317                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2318                         encode_reflection_type (assembly, pt, &buf);
2319                 }
2320         } else if (smb && smb->parameters) {
2321                 /* the property type is the last param */
2322                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2323                 for (i = 0; i < nparams; ++i) {
2324                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2325                         encode_reflection_type (assembly, pt, &buf);
2326                 }
2327         } else {
2328                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2329         }
2330
2331         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2332         sigbuffer_free (&buf);
2333         return idx;
2334 }
2335
2336 static void
2337 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2338 {
2339         MONO_REQ_GC_UNSAFE_MODE;
2340
2341         MonoDynamicTable *table;
2342         guint32 *values;
2343         guint num_methods = 0;
2344         guint32 semaidx;
2345
2346         /* 
2347          * we need to set things in the following tables:
2348          * PROPERTYMAP (info already filled in _get_type_info ())
2349          * PROPERTY    (rows already preallocated in _get_type_info ())
2350          * METHOD      (method info already done with the generic method code)
2351          * METHODSEMANTICS
2352          * CONSTANT
2353          */
2354         table = &assembly->tables [MONO_TABLE_PROPERTY];
2355         pb->table_idx = table->next_idx ++;
2356         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2357         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2358         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2359         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2360
2361         /* FIXME: we still don't handle 'other' methods */
2362         if (pb->get_method) num_methods ++;
2363         if (pb->set_method) num_methods ++;
2364
2365         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2366         table->rows += num_methods;
2367         alloc_table (table, table->rows);
2368
2369         if (pb->get_method) {
2370                 semaidx = table->next_idx ++;
2371                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2372                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2373                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2374                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2375         }
2376         if (pb->set_method) {
2377                 semaidx = table->next_idx ++;
2378                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2379                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2380                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2381                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2382         }
2383         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2384                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2385                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2386                 table->rows ++;
2387                 alloc_table (table, table->rows);
2388                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2389                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2390                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2391                 values [MONO_CONSTANT_TYPE] = field_type;
2392                 values [MONO_CONSTANT_PADDING] = 0;
2393         }
2394 }
2395
2396 static void
2397 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2398 {
2399         MONO_REQ_GC_UNSAFE_MODE;
2400
2401         MonoError error;
2402         MonoDynamicTable *table;
2403         guint32 *values;
2404         guint num_methods = 0;
2405         guint32 semaidx;
2406
2407         /* 
2408          * we need to set things in the following tables:
2409          * EVENTMAP (info already filled in _get_type_info ())
2410          * EVENT    (rows already preallocated in _get_type_info ())
2411          * METHOD      (method info already done with the generic method code)
2412          * METHODSEMANTICS
2413          */
2414         table = &assembly->tables [MONO_TABLE_EVENT];
2415         eb->table_idx = table->next_idx ++;
2416         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2417         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2418         values [MONO_EVENT_FLAGS] = eb->attrs;
2419         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, &error);
2420         mono_error_raise_exception (&error); /* FIXME don't raise here */
2421         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2422
2423         /*
2424          * FIXME: we still don't handle 'other' methods 
2425          */
2426         if (eb->add_method) num_methods ++;
2427         if (eb->remove_method) num_methods ++;
2428         if (eb->raise_method) num_methods ++;
2429
2430         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2431         table->rows += num_methods;
2432         alloc_table (table, table->rows);
2433
2434         if (eb->add_method) {
2435                 semaidx = table->next_idx ++;
2436                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2437                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2438                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2439                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2440         }
2441         if (eb->remove_method) {
2442                 semaidx = table->next_idx ++;
2443                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2444                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2445                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2446                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2447         }
2448         if (eb->raise_method) {
2449                 semaidx = table->next_idx ++;
2450                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2451                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2452                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2453                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2454         }
2455 }
2456
2457 static void
2458 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2459 {
2460         MONO_REQ_GC_UNSAFE_MODE;
2461
2462         MonoError error;
2463         MonoDynamicTable *table;
2464         guint32 num_constraints, i;
2465         guint32 *values;
2466         guint32 table_idx;
2467
2468         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2469         num_constraints = gparam->iface_constraints ?
2470                 mono_array_length (gparam->iface_constraints) : 0;
2471         table->rows += num_constraints;
2472         if (gparam->base_type)
2473                 table->rows++;
2474         alloc_table (table, table->rows);
2475
2476         if (gparam->base_type) {
2477                 table_idx = table->next_idx ++;
2478                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2479
2480                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, &error);
2481                 mono_error_raise_exception (&error); /* FIXME don't raise here */
2482                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2483                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2484         }
2485
2486         for (i = 0; i < num_constraints; i++) {
2487                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2488                         gparam->iface_constraints, gpointer, i);
2489
2490                 table_idx = table->next_idx ++;
2491                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2492
2493                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, &error);
2494                 mono_error_raise_exception (&error); /* FIXME don't raise here */
2495
2496                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2497                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2498         }
2499 }
2500
2501 static void
2502 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2503 {
2504         MONO_REQ_GC_UNSAFE_MODE;
2505
2506         GenericParamTableEntry *entry;
2507
2508         /*
2509          * The GenericParam table must be sorted according to the `owner' field.
2510          * We need to do this sorting prior to writing the GenericParamConstraint
2511          * table, since we have to use the final GenericParam table indices there
2512          * and they must also be sorted.
2513          */
2514
2515         entry = g_new0 (GenericParamTableEntry, 1);
2516         entry->owner = owner;
2517         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2518         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2519         entry->gparam = gparam;
2520         
2521         g_ptr_array_add (assembly->gen_params, entry);
2522 }
2523
2524 static gboolean
2525 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2526 {
2527         MONO_REQ_GC_UNSAFE_MODE;
2528
2529         MonoDynamicTable *table;
2530         MonoGenericParam *param;
2531         guint32 *values;
2532         guint32 table_idx;
2533
2534         mono_error_init (error);
2535
2536         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2537         table_idx = table->next_idx ++;
2538         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2539
2540         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2541         return_val_if_nok (error, FALSE);
2542
2543         param = gparam_type->data.generic_param;
2544
2545         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2546         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2547         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2548         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2549
2550         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2551                 return FALSE;
2552
2553         encode_constraints (entry->gparam, table_idx, assembly);
2554
2555         return TRUE;
2556 }
2557
2558 static guint32
2559 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2560 {
2561         MONO_REQ_GC_UNSAFE_MODE;
2562
2563         MonoDynamicTable *table;
2564         guint32 token;
2565         guint32 *values;
2566         guint32 cols [MONO_ASSEMBLY_SIZE];
2567         const char *pubkey;
2568         guint32 publen;
2569
2570         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2571                 return token;
2572
2573         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2574                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2575                 token = table->next_idx ++;
2576                 table->rows ++;
2577                 alloc_table (table, table->rows);
2578                 values = table->values + token * MONO_MODULEREF_SIZE;
2579                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2580
2581                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2582                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2583                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2584
2585                 return token;
2586         }
2587         
2588         if (assembly_is_dynamic (image->assembly))
2589                 /* FIXME: */
2590                 memset (cols, 0, sizeof (cols));
2591         else {
2592                 /* image->assembly->image is the manifest module */
2593                 image = image->assembly->image;
2594                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2595         }
2596
2597         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2598         token = table->next_idx ++;
2599         table->rows ++;
2600         alloc_table (table, table->rows);
2601         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2602         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2603         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2604         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2605         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2606         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2607         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2608         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2609         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2610
2611         if (strcmp ("", image->assembly->aname.culture)) {
2612                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2613                                 image->assembly->aname.culture);
2614         }
2615
2616         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2617                 guchar pubtoken [9];
2618                 pubtoken [0] = 8;
2619                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2620                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2621         } else {
2622                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2623         }
2624         token <<= MONO_RESOLUTION_SCOPE_BITS;
2625         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2626         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2627         return token;
2628 }
2629
2630 static guint32
2631 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2632 {
2633         MONO_REQ_GC_NEUTRAL_MODE;
2634
2635         MonoDynamicTable *table;
2636         guint32 *values;
2637         guint32 token;
2638         SigBuffer buf;
2639
2640         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2641                 return token;
2642
2643         sigbuffer_init (&buf, 32);
2644         switch (type->type) {
2645         case MONO_TYPE_FNPTR:
2646         case MONO_TYPE_PTR:
2647         case MONO_TYPE_SZARRAY:
2648         case MONO_TYPE_ARRAY:
2649         case MONO_TYPE_VAR:
2650         case MONO_TYPE_MVAR:
2651         case MONO_TYPE_GENERICINST:
2652                 encode_type (assembly, type, &buf);
2653                 break;
2654         case MONO_TYPE_CLASS:
2655         case MONO_TYPE_VALUETYPE: {
2656                 MonoClass *k = mono_class_from_mono_type (type);
2657                 if (!k || !k->generic_container) {
2658                         sigbuffer_free (&buf);
2659                         return 0;
2660                 }
2661                 encode_type (assembly, type, &buf);
2662                 break;
2663         }
2664         default:
2665                 sigbuffer_free (&buf);
2666                 return 0;
2667         }
2668
2669         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2670         if (assembly->save) {
2671                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2672                 alloc_table (table, table->rows + 1);
2673                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2674                 values [MONO_TYPESPEC_SIGNATURE] = token;
2675         }
2676         sigbuffer_free (&buf);
2677
2678         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2679         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2680         table->next_idx ++;
2681         return token;
2682 }
2683
2684 static guint32
2685 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2686 {
2687         MONO_REQ_GC_UNSAFE_MODE;
2688
2689         MonoDynamicTable *table;
2690         guint32 *values;
2691         guint32 token, scope, enclosing;
2692         MonoClass *klass;
2693
2694         /* if the type requires a typespec, we must try that first*/
2695         if (try_typespec && (token = create_typespec (assembly, type)))
2696                 return token;
2697         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2698         if (token)
2699                 return token;
2700         klass = mono_class_from_mono_type (type);
2701         if (!klass)
2702                 klass = mono_class_from_mono_type (type);
2703
2704         /*
2705          * If it's in the same module and not a generic type parameter:
2706          */
2707         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2708                         (type->type != MONO_TYPE_MVAR)) {
2709                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2710                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2711                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2712                 return token;
2713         }
2714
2715         if (klass->nested_in) {
2716                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2717                 /* get the typeref idx of the enclosing type */
2718                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2719                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2720         } else {
2721                 scope = resolution_scope_from_image (assembly, klass->image);
2722         }
2723         table = &assembly->tables [MONO_TABLE_TYPEREF];
2724         if (assembly->save) {
2725                 alloc_table (table, table->rows + 1);
2726                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2727                 values [MONO_TYPEREF_SCOPE] = scope;
2728                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2729                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2730         }
2731         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2732         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2733         table->next_idx ++;
2734         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2735         return token;
2736 }
2737
2738 /*
2739  * Despite the name, we handle also TypeSpec (with the above helper).
2740  */
2741 static guint32
2742 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2743 {
2744         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2745 }
2746
2747 #ifndef DISABLE_REFLECTION_EMIT
2748 static guint32
2749 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2750 {
2751         MONO_REQ_GC_NEUTRAL_MODE;
2752
2753         MonoDynamicTable *table;
2754         guint32 *values;
2755         guint32 token, pclass;
2756
2757         switch (parent & MONO_TYPEDEFORREF_MASK) {
2758         case MONO_TYPEDEFORREF_TYPEREF:
2759                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2760                 break;
2761         case MONO_TYPEDEFORREF_TYPESPEC:
2762                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2763                 break;
2764         case MONO_TYPEDEFORREF_TYPEDEF:
2765                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2766                 break;
2767         default:
2768                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2769                 return 0;
2770         }
2771         /* extract the index */
2772         parent >>= MONO_TYPEDEFORREF_BITS;
2773
2774         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2775
2776         if (assembly->save) {
2777                 alloc_table (table, table->rows + 1);
2778                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2779                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2780                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2781                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2782         }
2783
2784         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2785         table->next_idx ++;
2786
2787         return token;
2788 }
2789
2790 /*
2791  * Insert a memberef row into the metadata: the token that point to the memberref
2792  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2793  * mono_image_get_fieldref_token()).
2794  * The sig param is an index to an already built signature.
2795  */
2796 static guint32
2797 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2798 {
2799         MONO_REQ_GC_NEUTRAL_MODE;
2800
2801         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2802         return mono_image_add_memberef_row (assembly, parent, name, sig);
2803 }
2804
2805
2806 static guint32
2807 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2808 {
2809         MONO_REQ_GC_NEUTRAL_MODE;
2810
2811         guint32 token;
2812         MonoMethodSignature *sig;
2813         
2814         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2815
2816         if (create_typespec) {
2817                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2818                 if (token)
2819                         return token;
2820         } 
2821
2822         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2823         if (token && !create_typespec)
2824                 return token;
2825
2826         g_assert (!method->is_inflated);
2827         if (!token) {
2828                 /*
2829                  * A methodref signature can't contain an unmanaged calling convention.
2830                  */
2831                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2832                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2833                         sig->call_convention = MONO_CALL_DEFAULT;
2834                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2835                         method->name,  method_encode_signature (assembly, sig));
2836                 g_free (sig);
2837                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2838         }
2839
2840         if (create_typespec) {
2841                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2842                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2843                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2844
2845                 if (assembly->save) {
2846                         guint32 *values;
2847
2848                         alloc_table (table, table->rows + 1);
2849                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2850                         values [MONO_METHODSPEC_METHOD] = token;
2851                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2852                 }
2853
2854                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2855                 table->next_idx ++;
2856                 /*methodspec and memberef tokens are diferent, */
2857                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2858                 return token;
2859         }
2860         return token;
2861 }
2862
2863 static guint32
2864 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2865 {
2866         guint32 token, parent, sig;
2867         ReflectionMethodBuilder rmb;
2868         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2869         
2870         mono_error_init (error);
2871         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2872         if (token)
2873                 return token;
2874
2875         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2876                 return 0;
2877
2878         /*
2879          * A methodref signature can't contain an unmanaged calling convention.
2880          * Since some flags are encoded as part of call_conv, we need to check against it.
2881         */
2882         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2883                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2884
2885         sig = method_builder_encode_signature (assembly, &rmb);
2886
2887         if (tb->generic_params)
2888                 parent = create_generic_typespec (assembly, tb);
2889         else {
2890                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2891                 return_val_if_nok (error, 0);
2892
2893                 parent = mono_image_typedef_or_ref (assembly, t);
2894         }
2895
2896         char *name = mono_string_to_utf8 (method->name);
2897
2898         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2899         g_free (name);
2900
2901         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2902
2903         return token;
2904 }
2905
2906 static guint32
2907 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2908                                      const gchar *name, guint32 sig)
2909 {
2910         MonoDynamicTable *table;
2911         guint32 token;
2912         guint32 *values;
2913         
2914         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2915
2916         if (assembly->save) {
2917                 alloc_table (table, table->rows + 1);
2918                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2919                 values [MONO_MEMBERREF_CLASS] = original;
2920                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2921                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2922         }
2923
2924         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2925         table->next_idx ++;
2926
2927         return token;
2928 }
2929
2930 static guint32
2931 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2932 {
2933         SigBuffer buf;
2934         int i;
2935         guint32 nparams = mono_array_length (mb->generic_params);
2936         guint32 idx;
2937
2938         if (!assembly->save)
2939                 return 0;
2940
2941         sigbuffer_init (&buf, 32);
2942
2943         sigbuffer_add_value (&buf, 0xa);
2944         sigbuffer_add_value (&buf, nparams);
2945
2946         for (i = 0; i < nparams; i++) {
2947                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2948                 sigbuffer_add_value (&buf, i);
2949         }
2950
2951         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2952         sigbuffer_free (&buf);
2953         return idx;
2954 }
2955
2956 static guint32
2957 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
2958 {
2959         MonoDynamicTable *table;
2960         guint32 *values;
2961         guint32 token, mtoken = 0;
2962
2963         mono_error_init (error);
2964         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2965         if (token)
2966                 return token;
2967
2968         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2969
2970         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2971         if (!mono_error_ok (error))
2972                 return 0;
2973
2974         switch (mono_metadata_token_table (mtoken)) {
2975         case MONO_TABLE_MEMBERREF:
2976                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2977                 break;
2978         case MONO_TABLE_METHOD:
2979                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2980                 break;
2981         default:
2982                 g_assert_not_reached ();
2983         }
2984
2985         if (assembly->save) {
2986                 alloc_table (table, table->rows + 1);
2987                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2988                 values [MONO_METHODSPEC_METHOD] = mtoken;
2989                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2990         }
2991
2992         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2993         table->next_idx ++;
2994
2995         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2996         return token;
2997 }
2998
2999 static guint32
3000 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3001 {
3002         guint32 token;
3003
3004         mono_error_init (error);
3005
3006         if (mb->generic_params && create_methodspec) 
3007                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3008
3009         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3010         if (token)
3011                 return token;
3012
3013         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3014         if (!mono_error_ok (error))
3015                 return 0;
3016         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3017         return token;
3018 }
3019
3020 static guint32
3021 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3022 {
3023         guint32 token, parent, sig;
3024         ReflectionMethodBuilder rmb;
3025         char *name;
3026         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3027         
3028         mono_error_init (error);
3029         
3030         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3031         if (token)
3032                 return token;
3033
3034         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3035                 return 0;
3036
3037         if (tb->generic_params)
3038                 parent = create_generic_typespec (assembly, tb);
3039         else {
3040                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3041                 return_val_if_nok (error, 0);
3042                 parent = mono_image_typedef_or_ref (assembly, type);
3043         }
3044         
3045         name = mono_string_to_utf8 (rmb.name);
3046         sig = method_builder_encode_signature (assembly, &rmb);
3047
3048         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3049
3050         g_free (name);
3051         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3052         return token;
3053 }
3054 #endif
3055
3056 static gboolean
3057 is_field_on_inst (MonoClassField *field)
3058 {
3059         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3060 }
3061
3062 /*
3063  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3064  */
3065 static MonoType*
3066 get_field_on_inst_generic_type (MonoClassField *field)
3067 {
3068         MonoClass *klass, *gtd;
3069         MonoDynamicGenericClass *dgclass;
3070         int field_index;
3071
3072         g_assert (is_field_on_inst (field));
3073
3074         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3075
3076         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3077                 field_index = field - dgclass->fields;
3078                 return dgclass->field_generic_types [field_index];              
3079         }
3080
3081         klass = field->parent;
3082         gtd = klass->generic_class->container_class;
3083
3084         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3085                 field_index = field - klass->fields;
3086                 return gtd->fields [field_index].type;
3087         }
3088
3089         g_assert_not_reached ();
3090         return 0;
3091 }
3092
3093 #ifndef DISABLE_REFLECTION_EMIT
3094 static guint32
3095 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3096 {
3097         MonoType *type;
3098         guint32 token;
3099
3100         g_assert (field);
3101         g_assert (field->parent);
3102
3103         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3104         if (token)
3105                 return token;
3106
3107         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3108                 int index = field - field->parent->fields;
3109                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3110         } else {
3111                 if (is_field_on_inst (field))
3112                         type = get_field_on_inst_generic_type (field);
3113                 else
3114                         type = mono_field_get_type (field);
3115         }
3116         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3117                                                                                         mono_field_get_name (field),
3118                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3119         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3120         return token;
3121 }
3122
3123 static guint32
3124 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3125 {
3126         MonoError error;
3127         guint32 token;
3128         MonoClass *klass;
3129         MonoGenericClass *gclass;
3130         MonoType *type;
3131         char *name;
3132
3133         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3134         if (token)
3135                 return token;
3136         if (is_sre_field_builder (mono_object_class (f->fb))) {
3137                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3138                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
3139                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3140                 klass = mono_class_from_mono_type (type);
3141                 gclass = type->data.generic_class;
3142                 g_assert (gclass->is_dynamic);
3143
3144                 name = mono_string_to_utf8 (fb->name);
3145                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
3146                                                                                                 field_encode_signature (assembly, fb));
3147                 g_free (name);          
3148         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3149                 guint32 sig;
3150                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3151
3152                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
3153                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3154                 klass = mono_class_from_mono_type (type);
3155
3156                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3157                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3158         } else {
3159                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3160                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3161         }
3162
3163         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3164         return token;
3165 }
3166
3167 static guint32
3168 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3169 {
3170         guint32 sig, token;
3171         MonoClass *klass;
3172         MonoGenericClass *gclass;
3173         MonoType *type;
3174
3175         mono_error_init (error);
3176
3177         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3178
3179         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3180         if (token)
3181                 return token;
3182
3183         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3184                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3185                 ReflectionMethodBuilder rmb;
3186                 char *name;
3187
3188                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3189                 return_val_if_nok (error, 0);
3190                 klass = mono_class_from_mono_type (type);
3191
3192                 gclass = type->data.generic_class;
3193                 g_assert (gclass->is_dynamic);
3194
3195                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3196                         return 0;
3197
3198                 name = mono_string_to_utf8 (rmb.name);
3199
3200                 sig = method_builder_encode_signature (assembly, &rmb);
3201
3202                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3203                 g_free (name);
3204         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3205                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3206
3207                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3208                 return_val_if_nok (error, 0);
3209                 klass = mono_class_from_mono_type (type);
3210
3211                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3212                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3213         } else {
3214                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3215                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3216         }
3217
3218
3219         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3220         return token;
3221 }
3222
3223 static MonoMethod*
3224 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3225 {
3226         MonoClass *klass;
3227         MonoGenericContext tmp_context;
3228         MonoType **type_argv;
3229         MonoGenericInst *ginst;
3230         MonoMethod *method, *inflated;
3231         int count, i;
3232
3233         mono_error_init (error);
3234
3235         init_type_builder_generics ((MonoObject*)m->inst);
3236
3237         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3238         return_val_if_nok (error, NULL);
3239
3240         klass = method->klass;
3241
3242         if (m->method_args == NULL)
3243                 return method;
3244
3245         if (method->is_inflated)
3246                 method = ((MonoMethodInflated *) method)->declaring;
3247
3248         count = mono_array_length (m->method_args);
3249
3250         type_argv = g_new0 (MonoType *, count);
3251         for (i = 0; i < count; i++) {
3252                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3253                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3254                 return_val_if_nok (error, NULL);
3255         }
3256         ginst = mono_metadata_get_generic_inst (count, type_argv);
3257         g_free (type_argv);
3258
3259         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3260         tmp_context.method_inst = ginst;
3261
3262         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3263         mono_error_assert_ok (error);
3264         return inflated;
3265 }
3266
3267 static guint32
3268 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3269 {
3270         guint32 sig, token = 0;
3271         MonoType *type;
3272         MonoClass *klass;
3273
3274         mono_error_init (error);
3275
3276         if (m->method_args) {
3277                 MonoMethod *inflated;
3278
3279                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3280                 return_val_if_nok (error, 0);
3281
3282                 if (create_methodspec)
3283                         token = mono_image_get_methodspec_token (assembly, inflated);
3284                 else
3285                         token = mono_image_get_inflated_method_token (assembly, inflated);
3286                 return token;
3287         }
3288
3289         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3290         if (token)
3291                 return token;
3292
3293         if (is_sre_method_builder (mono_object_class (m->mb))) {
3294                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3295                 MonoGenericClass *gclass;
3296                 ReflectionMethodBuilder rmb;
3297                 char *name;
3298
3299                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3300                 return_val_if_nok (error, 0);
3301                 klass = mono_class_from_mono_type (type);
3302                 gclass = type->data.generic_class;
3303                 g_assert (gclass->is_dynamic);
3304
3305                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3306                         return 0;
3307
3308                 name = mono_string_to_utf8 (rmb.name);
3309
3310                 sig = method_builder_encode_signature (assembly, &rmb);
3311
3312                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3313                 g_free (name);          
3314         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3315                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3316
3317                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3318                 return_val_if_nok (error, 0);
3319                 klass = mono_class_from_mono_type (type);
3320
3321                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3322                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3323         } else {
3324                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3325                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3326         }
3327
3328         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3329         return token;
3330 }
3331
3332 static guint32
3333 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3334 {
3335         SigBuffer buf;
3336         int i;
3337         guint32 nparams = context->method_inst->type_argc;
3338         guint32 idx;
3339
3340         if (!assembly->save)
3341                 return 0;
3342
3343         sigbuffer_init (&buf, 32);
3344         /*
3345          * FIXME: vararg, explicit_this, differenc call_conv values...
3346          */
3347         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3348         sigbuffer_add_value (&buf, nparams);
3349
3350         for (i = 0; i < nparams; i++)
3351                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3352
3353         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3354         sigbuffer_free (&buf);
3355         return idx;
3356 }
3357
3358 static guint32
3359 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3360 {
3361         MonoDynamicTable *table;
3362         guint32 *values;
3363         guint32 token, mtoken = 0, sig;
3364         MonoMethodInflated *imethod;
3365         MonoMethod *declaring;
3366
3367         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3368
3369         g_assert (method->is_inflated);
3370         imethod = (MonoMethodInflated *) method;
3371         declaring = imethod->declaring;
3372
3373         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3374         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3375
3376         if (!mono_method_signature (declaring)->generic_param_count)
3377                 return mtoken;
3378
3379         switch (mono_metadata_token_table (mtoken)) {
3380         case MONO_TABLE_MEMBERREF:
3381                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3382                 break;
3383         case MONO_TABLE_METHOD:
3384                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3385                 break;
3386         default:
3387                 g_assert_not_reached ();
3388         }
3389
3390         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3391
3392         if (assembly->save) {
3393                 alloc_table (table, table->rows + 1);
3394                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3395                 values [MONO_METHODSPEC_METHOD] = mtoken;
3396                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3397         }
3398
3399         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3400         table->next_idx ++;
3401
3402         return token;
3403 }
3404
3405 static guint32
3406 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3407 {
3408         MonoMethodInflated *imethod;
3409         guint32 token;
3410         
3411         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3412         if (token)
3413                 return token;
3414
3415         g_assert (method->is_inflated);
3416         imethod = (MonoMethodInflated *) method;
3417
3418         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3419                 token = method_encode_methodspec (assembly, method);
3420         } else {
3421                 guint32 sig = method_encode_signature (
3422                         assembly, mono_method_signature (imethod->declaring));
3423                 token = mono_image_get_memberref_token (
3424                         assembly, &method->klass->byval_arg, method->name, sig);
3425         }
3426
3427         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3428         return token;
3429 }
3430
3431 static guint32
3432 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3433 {
3434         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3435         guint32 sig, token;
3436
3437         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3438         token = mono_image_get_memberref_token (
3439                 assembly, &m->klass->byval_arg, m->name, sig);
3440
3441         return token;
3442 }
3443
3444 static guint32
3445 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3446 {
3447         MonoError error;
3448         MonoDynamicTable *table;
3449         MonoClass *klass;
3450         MonoType *type;
3451         guint32 *values;
3452         guint32 token;
3453         SigBuffer buf;
3454         int count, i;
3455
3456         /*
3457          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3458          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3459          * Because of this, we must not insert it into the `typeref' hash table.
3460          */
3461         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
3462         mono_error_raise_exception (&error); /* FIXME don't raise here */
3463         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3464         if (token)
3465                 return token;
3466
3467         sigbuffer_init (&buf, 32);
3468
3469         g_assert (tb->generic_params);
3470         klass = mono_class_from_mono_type (type);
3471
3472         if (tb->generic_container)
3473                 mono_reflection_create_generic_class (tb);
3474
3475         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3476         g_assert (klass->generic_container);
3477         sigbuffer_add_value (&buf, klass->byval_arg.type);
3478         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3479
3480         count = mono_array_length (tb->generic_params);
3481         sigbuffer_add_value (&buf, count);
3482         for (i = 0; i < count; i++) {
3483                 MonoReflectionGenericParam *gparam;
3484
3485                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3486                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
3487                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3488
3489                 encode_type (assembly, gparam_type, &buf);
3490         }
3491
3492         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3493
3494         if (assembly->save) {
3495                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3496                 alloc_table (table, table->rows + 1);
3497                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3498                 values [MONO_TYPESPEC_SIGNATURE] = token;
3499         }
3500         sigbuffer_free (&buf);
3501
3502         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3503         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3504         table->next_idx ++;
3505         return token;
3506 }
3507
3508 /*
3509  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3510  */
3511 static MonoType*
3512 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3513 {
3514         MonoError error;
3515         int i, count, len, pos;
3516         MonoType *t;
3517
3518         count = 0;
3519         if (modreq)
3520                 count += mono_array_length (modreq);
3521         if (modopt)
3522                 count += mono_array_length (modopt);
3523
3524         if (count == 0)
3525                 return mono_metadata_type_dup (NULL, type);
3526
3527         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3528         t = (MonoType *)g_malloc (len);
3529         memcpy (t, type, MONO_SIZEOF_TYPE);
3530
3531         t->num_mods = count;
3532         pos = 0;
3533         if (modreq) {
3534                 for (i = 0; i < mono_array_length (modreq); ++i) {
3535                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, &error);
3536                         mono_error_raise_exception (&error); /* FIXME don't raise here */
3537                         t->modifiers [pos].required = 1;
3538                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3539                         pos ++;
3540                 }
3541         }
3542         if (modopt) {
3543                 for (i = 0; i < mono_array_length (modopt); ++i) {
3544                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, &error);
3545                         mono_error_raise_exception (&error); /* FIXME don't raise here */
3546                         t->modifiers [pos].required = 0;
3547                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3548                         pos ++;
3549                 }
3550         }
3551
3552         return t;
3553 }
3554
3555 static void
3556 init_type_builder_generics (MonoObject *type)
3557 {
3558         MonoReflectionTypeBuilder *tb;
3559
3560         if (!is_sre_type_builder(mono_object_class (type)))
3561                 return;
3562         tb = (MonoReflectionTypeBuilder *)type;
3563
3564         if (tb && tb->generic_container)
3565                 mono_reflection_create_generic_class (tb);
3566 }
3567
3568 static guint32
3569 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3570 {
3571         MonoError error;
3572         MonoDynamicTable *table;
3573         MonoType *custom = NULL, *type;
3574         guint32 *values;
3575         guint32 token, pclass, parent, sig;
3576         gchar *name;
3577
3578         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3579         if (token)
3580                 return token;
3581
3582         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, &error);
3583         mono_error_raise_exception (&error); /* FIXME don't raise here */
3584         /* FIXME: is this call necessary? */
3585         mono_class_from_mono_type (typeb);
3586         name = mono_string_to_utf8 (fb->name);
3587
3588         /*FIXME this is one more layer of ugliness due how types are created.*/
3589         init_type_builder_generics (fb->type);
3590
3591         /* fb->type does not include the custom modifiers */
3592         /* FIXME: We should do this in one place when a fieldbuilder is created */
3593         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
3594         mono_error_raise_exception (&error); /* FIXME don't raise here */
3595
3596         if (fb->modreq || fb->modopt)
3597                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3598
3599         sig = fieldref_encode_signature (assembly, NULL, type);
3600         g_free (custom);
3601
3602         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3603         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3604         
3605         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3606         parent >>= MONO_TYPEDEFORREF_BITS;
3607
3608         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3609
3610         if (assembly->save) {
3611                 alloc_table (table, table->rows + 1);
3612                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3613                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3614                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3615                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3616         }
3617
3618         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3619         table->next_idx ++;
3620         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3621         g_free (name);
3622         return token;
3623 }
3624
3625 static guint32
3626 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3627 {
3628         SigBuffer buf;
3629         guint32 nargs;
3630         guint32 i, idx;
3631
3632         if (!assembly->save)
3633                 return 0;
3634
3635         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3636         g_assert (helper->type == 2);
3637
3638         if (helper->arguments)
3639                 nargs = mono_array_length (helper->arguments);
3640         else
3641                 nargs = 0;
3642
3643         sigbuffer_init (&buf, 32);
3644
3645         /* Encode calling convention */
3646         /* Change Any to Standard */
3647         if ((helper->call_conv & 0x03) == 0x03)
3648                 helper->call_conv = 0x01;
3649         /* explicit_this implies has_this */
3650         if (helper->call_conv & 0x40)
3651                 helper->call_conv &= 0x20;
3652
3653         if (helper->call_conv == 0) { /* Unmanaged */
3654                 idx = helper->unmanaged_call_conv - 1;
3655         } else {
3656                 /* Managed */
3657                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3658                 if (helper->call_conv & 0x02) /* varargs */
3659                         idx += 0x05;
3660         }
3661
3662         sigbuffer_add_byte (&buf, idx);
3663         sigbuffer_add_value (&buf, nargs);
3664         encode_reflection_type (assembly, helper->return_type, &buf);
3665         for (i = 0; i < nargs; ++i) {
3666                 MonoArray *modreqs = NULL;
3667                 MonoArray *modopts = NULL;
3668                 MonoReflectionType *pt;
3669
3670                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3671                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3672                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3673                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3674
3675                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3676                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3677                 encode_reflection_type (assembly, pt, &buf);
3678         }
3679         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3680         sigbuffer_free (&buf);
3681
3682         return idx;
3683 }
3684
3685 static guint32 
3686 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3687 {
3688         guint32 idx;
3689         MonoDynamicTable *table;
3690         guint32 *values;
3691
3692         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3693         idx = table->next_idx ++;
3694         table->rows ++;
3695         alloc_table (table, table->rows);
3696         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3697
3698         values [MONO_STAND_ALONE_SIGNATURE] =
3699                 mono_reflection_encode_sighelper (assembly, helper);
3700
3701         return idx;
3702 }
3703
3704 static int
3705 reflection_cc_to_file (int call_conv) {
3706         switch (call_conv & 0x3) {
3707         case 0:
3708         case 1: return MONO_CALL_DEFAULT;
3709         case 2: return MONO_CALL_VARARG;
3710         default:
3711                 g_assert_not_reached ();
3712         }
3713         return 0;
3714 }
3715 #endif /* !DISABLE_REFLECTION_EMIT */
3716
3717 typedef struct {
3718         MonoType *parent;
3719         MonoMethodSignature *sig;
3720         char *name;
3721         guint32 token;
3722 } ArrayMethod;
3723
3724 #ifndef DISABLE_REFLECTION_EMIT
3725 static guint32
3726 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3727 {
3728         MonoError error;
3729         guint32 nparams, i;
3730         GList *tmp;
3731         char *name;
3732         MonoMethodSignature *sig;
3733         ArrayMethod *am;
3734         MonoType *mtype;
3735
3736         name = mono_string_to_utf8 (m->name);
3737         nparams = mono_array_length (m->parameters);
3738         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3739         sig->hasthis = 1;
3740         sig->sentinelpos = -1;
3741         sig->call_convention = reflection_cc_to_file (m->call_conv);
3742         sig->param_count = nparams;
3743         if (m->ret) {
3744                 sig->ret = mono_reflection_type_get_handle (m->ret, &error);
3745                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3746         } else
3747                 sig->ret = &mono_defaults.void_class->byval_arg;
3748
3749         mtype = mono_reflection_type_get_handle (m->parent, &error);
3750         mono_error_raise_exception (&error); /* FIXME don't raise here */
3751
3752         for (i = 0; i < nparams; ++i) {
3753                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, &error);
3754                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3755         }
3756
3757         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3758                 am = (ArrayMethod *)tmp->data;
3759                 if (strcmp (name, am->name) == 0 && 
3760                                 mono_metadata_type_equal (am->parent, mtype) &&
3761                                 mono_metadata_signature_equal (am->sig, sig)) {
3762                         g_free (name);
3763                         g_free (sig);
3764                         m->table_idx = am->token & 0xffffff;
3765                         return am->token;
3766                 }
3767         }
3768         am = g_new0 (ArrayMethod, 1);
3769         am->name = name;
3770         am->sig = sig;
3771         am->parent = mtype;
3772         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3773                 method_encode_signature (assembly, sig));
3774         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3775         m->table_idx = am->token & 0xffffff;
3776         return am->token;
3777 }
3778
3779 /*
3780  * Insert into the metadata tables all the info about the TypeBuilder tb.
3781  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3782  */
3783 static gboolean
3784 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3785 {
3786         MonoDynamicTable *table;
3787         guint *values;
3788         int i, is_object = 0, is_system = 0;
3789         char *n;
3790
3791         mono_error_init (error);
3792
3793         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3794         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3795         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3796         n = mono_string_to_utf8 (tb->name);
3797         if (strcmp (n, "Object") == 0)
3798                 is_object++;
3799         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3800         g_free (n);
3801         n = mono_string_to_utf8 (tb->nspace);
3802         if (strcmp (n, "System") == 0)
3803                 is_system++;
3804         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3805         g_free (n);
3806         if (tb->parent && !(is_system && is_object) && 
3807                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3808                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3809                 return_val_if_nok (error, FALSE);
3810                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3811         } else {
3812                 values [MONO_TYPEDEF_EXTENDS] = 0;
3813         }
3814         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3815         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3816
3817         /*
3818          * if we have explicitlayout or sequentiallayouts, output data in the
3819          * ClassLayout table.
3820          */
3821         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3822                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3823                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3824                 table->rows++;
3825                 alloc_table (table, table->rows);
3826                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3827                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3828                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3829                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3830         }
3831
3832         /* handle interfaces */
3833         if (tb->interfaces) {
3834                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3835                 i = table->rows;
3836                 table->rows += mono_array_length (tb->interfaces);
3837                 alloc_table (table, table->rows);
3838                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3839                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3840                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3841                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3842                         return_val_if_nok (error, FALSE);
3843                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3844                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3845                         values += MONO_INTERFACEIMPL_SIZE;
3846                 }
3847         }
3848
3849         /* handle fields */
3850         if (tb->fields) {
3851                 table = &assembly->tables [MONO_TABLE_FIELD];
3852                 table->rows += tb->num_fields;
3853                 alloc_table (table, table->rows);
3854                 for (i = 0; i < tb->num_fields; ++i)
3855                         mono_image_get_field_info (
3856                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3857         }
3858
3859         /* handle constructors */
3860         if (tb->ctors) {
3861                 table = &assembly->tables [MONO_TABLE_METHOD];
3862                 table->rows += mono_array_length (tb->ctors);
3863                 alloc_table (table, table->rows);
3864                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3865                         if (!mono_image_get_ctor_info (domain,
3866                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3867                                                        assembly, error))
3868                                 return FALSE;
3869                 }
3870         }
3871
3872         /* handle methods */
3873         if (tb->methods) {
3874                 table = &assembly->tables [MONO_TABLE_METHOD];
3875                 table->rows += tb->num_methods;
3876                 alloc_table (table, table->rows);
3877                 for (i = 0; i < tb->num_methods; ++i) {
3878                         if (!mono_image_get_method_info (
3879                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3880                                 return FALSE;
3881                 }
3882         }
3883
3884         /* Do the same with properties etc.. */
3885         if (tb->events && mono_array_length (tb->events)) {
3886                 table = &assembly->tables [MONO_TABLE_EVENT];
3887                 table->rows += mono_array_length (tb->events);
3888                 alloc_table (table, table->rows);
3889                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3890                 table->rows ++;
3891                 alloc_table (table, table->rows);
3892                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3893                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3894                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3895                 for (i = 0; i < mono_array_length (tb->events); ++i)
3896                         mono_image_get_event_info (
3897                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3898         }
3899         if (tb->properties && mono_array_length (tb->properties)) {
3900                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3901                 table->rows += mono_array_length (tb->properties);
3902                 alloc_table (table, table->rows);
3903                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3904                 table->rows ++;
3905                 alloc_table (table, table->rows);
3906                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3907                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3908                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3909                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3910                         mono_image_get_property_info (
3911                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3912         }
3913
3914         /* handle generic parameters */
3915         if (tb->generic_params) {
3916                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3917                 table->rows += mono_array_length (tb->generic_params);
3918                 alloc_table (table, table->rows);
3919                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3920                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3921
3922                         mono_image_get_generic_param_info (
3923                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3924                 }
3925         }
3926
3927         mono_image_add_decl_security (assembly, 
3928                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3929
3930         if (tb->subtypes) {
3931                 MonoDynamicTable *ntable;
3932                 
3933                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3934                 ntable->rows += mono_array_length (tb->subtypes);
3935                 alloc_table (ntable, ntable->rows);
3936                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3937
3938                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3939                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3940
3941                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3942                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3943                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3944                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3945                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3946                                 ntable->next_idx, ntable->rows);*/
3947                         values += MONO_NESTED_CLASS_SIZE;
3948                         ntable->next_idx++;
3949                 }
3950         }
3951
3952         return TRUE;
3953 }
3954 #endif
3955
3956 static void
3957 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3958 {
3959         int i;
3960
3961         mono_ptr_array_append (*types, type);
3962
3963         if (!type->subtypes)
3964                 return;
3965
3966         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3967                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3968                 collect_types (types, subtype);
3969         }
3970 }
3971
3972 static gint
3973 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3974 {
3975         if ((*type1)->table_idx < (*type2)->table_idx)
3976                 return -1;
3977         else
3978                 if ((*type1)->table_idx > (*type2)->table_idx)
3979                         return 1;
3980         else
3981                 return 0;
3982 }
3983
3984 static gboolean
3985 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3986         int i;
3987
3988         mono_error_init (error);
3989         if (!pinfo)
3990                 return TRUE;
3991         for (i = 0; i < mono_array_length (pinfo); ++i) {
3992                 MonoReflectionParamBuilder *pb;
3993                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3994                 if (!pb)
3995                         continue;
3996                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3997                         return FALSE;
3998         }
3999
4000         return TRUE;
4001 }
4002
4003 static gboolean
4004 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4005         int i;
4006
4007         mono_error_init (error);
4008         
4009         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4010                 return FALSE;
4011         if (tb->fields) {
4012                 for (i = 0; i < tb->num_fields; ++i) {
4013                         MonoReflectionFieldBuilder* fb;
4014                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4015                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4016                                 return FALSE;
4017                 }
4018         }
4019         if (tb->events) {
4020                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4021                         MonoReflectionEventBuilder* eb;
4022                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4023                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4024                                 return FALSE;
4025                 }
4026         }
4027         if (tb->properties) {
4028                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4029                         MonoReflectionPropertyBuilder* pb;
4030                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4031                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4032                                 return FALSE;
4033                 }
4034         }
4035         if (tb->ctors) {
4036                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4037                         MonoReflectionCtorBuilder* cb;
4038                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4039                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4040                             !params_add_cattrs (assembly, cb->pinfo, error))
4041                                 return FALSE;
4042                 }
4043         }
4044
4045         if (tb->methods) {
4046                 for (i = 0; i < tb->num_methods; ++i) {
4047                         MonoReflectionMethodBuilder* mb;
4048                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4049                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4050                             !params_add_cattrs (assembly, mb->pinfo, error))
4051                                 return FALSE;
4052                 }
4053         }
4054
4055         if (tb->subtypes) {
4056                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4057                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4058                                 return FALSE;
4059                 }
4060         }
4061
4062         return TRUE;
4063 }
4064
4065 static gboolean
4066 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4067 {
4068         int i;
4069         
4070         mono_error_init (error);
4071
4072         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4073                 return FALSE;
4074
4075         if (moduleb->global_methods) {
4076                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4077                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4078                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4079                             !params_add_cattrs (assembly, mb->pinfo, error))
4080                                 return FALSE;
4081                 }
4082         }
4083
4084         if (moduleb->global_fields) {
4085                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4086                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4087                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4088                                 return FALSE;
4089                 }
4090         }
4091         
4092         if (moduleb->types) {
4093                 for (i = 0; i < moduleb->num_types; ++i) {
4094                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4095                                 return FALSE;
4096                 }
4097         }
4098
4099         return TRUE;
4100 }
4101
4102 static void
4103 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4104 {
4105         MonoDynamicTable *table;
4106         guint32 *values;
4107         char blob_size [6];
4108         guchar hash [20];
4109         char *b = blob_size;
4110         char *dir, *path;
4111
4112         table = &assembly->tables [MONO_TABLE_FILE];
4113         table->rows++;
4114         alloc_table (table, table->rows);
4115         values = table->values + table->next_idx * MONO_FILE_SIZE;
4116         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4117         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4118         if (image_is_dynamic (module->image)) {
4119                 /* This depends on the fact that the main module is emitted last */
4120                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4121                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4122         } else {
4123                 dir = NULL;
4124                 path = g_strdup (module->image->name);
4125         }
4126         mono_sha1_get_digest_from_file (path, hash);
4127         g_free (dir);
4128         g_free (path);
4129         mono_metadata_encode_value (20, b, &b);
4130         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4131         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4132         table->next_idx ++;
4133 }
4134
4135 static void
4136 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4137 {
4138         MonoDynamicTable *table;
4139         int i;
4140
4141         table = &assembly->tables [MONO_TABLE_MODULE];
4142         mb->table_idx = table->next_idx ++;
4143         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4144         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4145         i /= 16;
4146         ++i;
4147         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4148         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4149         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4150         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4151 }
4152
4153 static guint32
4154 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4155         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4156 {
4157         MonoDynamicTable *table;
4158         guint32 *values;
4159         guint32 visib, res;
4160
4161         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4162         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4163                 return 0;
4164
4165         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4166         table->rows++;
4167         alloc_table (table, table->rows);
4168         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4169
4170         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4171         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4172         if (klass->nested_in)
4173                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4174         else
4175                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4176         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4177         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4178
4179         res = table->next_idx;
4180
4181         table->next_idx ++;
4182
4183         /* Emit nested types */
4184         if (klass->ext && klass->ext->nested_classes) {
4185                 GList *tmp;
4186
4187                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4188                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4189         }
4190
4191         return res;
4192 }
4193
4194 static void
4195 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4196         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4197 {
4198         MonoError error;
4199         MonoClass *klass;
4200         guint32 idx, i;
4201
4202         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
4203         mono_error_raise_exception (&error); /* FIXME don't raise here */
4204
4205         klass = mono_class_from_mono_type (t);
4206
4207         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4208
4209         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4210                                                                                                    parent_index, assembly);
4211
4212         /* 
4213          * Emit nested types
4214          * We need to do this ourselves since klass->nested_classes is not set up.
4215          */
4216         if (tb->subtypes) {
4217                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4218                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4219         }
4220 }
4221
4222 static void
4223 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4224         guint32 module_index, MonoDynamicImage *assembly)
4225 {
4226         MonoImage *image = module->image;
4227         MonoTableInfo  *t;
4228         guint32 i;
4229
4230         t = &image->tables [MONO_TABLE_TYPEDEF];
4231
4232         for (i = 0; i < t->rows; ++i) {
4233                 MonoError error;
4234                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4235                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4236
4237                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4238                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4239         }
4240 }
4241
4242 static void
4243 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4244 {
4245         MonoDynamicTable *table;
4246         guint32 *values;
4247         guint32 scope, scope_idx, impl, current_idx;
4248         gboolean forwarder = TRUE;
4249         gpointer iter = NULL;
4250         MonoClass *nested;
4251
4252         if (klass->nested_in) {
4253                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4254                 forwarder = FALSE;
4255         } else {
4256                 scope = resolution_scope_from_image (assembly, klass->image);
4257                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4258                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4259                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4260         }
4261
4262         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4263
4264         table->rows++;
4265         alloc_table (table, table->rows);
4266         current_idx = table->next_idx;
4267         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4268
4269         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4270         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4271         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4272         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4273         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4274
4275         table->next_idx++;
4276
4277         while ((nested = mono_class_get_nested_types (klass, &iter)))
4278                 add_exported_type (assemblyb, assembly, nested, current_idx);
4279 }
4280
4281 static void
4282 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4283 {
4284         MonoError error;
4285         MonoClass *klass;
4286         int i;
4287
4288         if (!assemblyb->type_forwarders)
4289                 return;
4290
4291         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4292                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4293                 MonoType *type;
4294                 if (!t)
4295                         continue;
4296
4297                 type = mono_reflection_type_get_handle (t, &error);
4298                 mono_error_assert_ok (&error);
4299                 g_assert (type);
4300
4301                 klass = mono_class_from_mono_type (type);
4302
4303                 add_exported_type (assemblyb, assembly, klass, 0);
4304         }
4305 }
4306
4307 #define align_pointer(base,p)\
4308         do {\
4309                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4310                 if (__diff & 3)\
4311                         (p) += 4 - (__diff & 3);\
4312         } while (0)
4313
4314 static int
4315 compare_constants (const void *a, const void *b)
4316 {
4317         const guint32 *a_values = (const guint32 *)a;
4318         const guint32 *b_values = (const guint32 *)b;
4319         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4320 }
4321
4322 static int
4323 compare_semantics (const void *a, const void *b)
4324 {
4325         const guint32 *a_values = (const guint32 *)a;
4326         const guint32 *b_values = (const guint32 *)b;
4327         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4328         if (assoc)
4329                 return assoc;
4330         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4331 }
4332
4333 static int
4334 compare_custom_attrs (const void *a, const void *b)
4335 {
4336         const guint32 *a_values = (const guint32 *)a;
4337         const guint32 *b_values = (const guint32 *)b;
4338
4339         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4340 }
4341
4342 static int
4343 compare_field_marshal (const void *a, const void *b)
4344 {
4345         const guint32 *a_values = (const guint32 *)a;
4346         const guint32 *b_values = (const guint32 *)b;
4347
4348         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4349 }
4350
4351 static int
4352 compare_nested (const void *a, const void *b)
4353 {
4354         const guint32 *a_values = (const guint32 *)a;
4355         const guint32 *b_values = (const guint32 *)b;
4356
4357         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4358 }
4359
4360 static int
4361 compare_genericparam (const void *a, const void *b)
4362 {
4363         MonoError error;
4364         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4365         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4366
4367         if ((*b_entry)->owner == (*a_entry)->owner) {
4368                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4369                 mono_error_assert_ok (&error);
4370                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4371                 mono_error_assert_ok (&error);
4372                 return 
4373                         mono_type_get_generic_param_num (a_type) -
4374                         mono_type_get_generic_param_num (b_type);
4375         } else
4376                 return (*a_entry)->owner - (*b_entry)->owner;
4377 }
4378
4379 static int
4380 compare_declsecurity_attrs (const void *a, const void *b)
4381 {
4382         const guint32 *a_values = (const guint32 *)a;
4383         const guint32 *b_values = (const guint32 *)b;
4384
4385         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4386 }
4387
4388 static int
4389 compare_interface_impl (const void *a, const void *b)
4390 {
4391         const guint32 *a_values = (const guint32 *)a;
4392         const guint32 *b_values = (const guint32 *)b;
4393
4394         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4395         if (klass)
4396                 return klass;
4397
4398         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4399 }
4400
4401 static void
4402 pad_heap (MonoDynamicStream *sh)
4403 {
4404         if (sh->index & 3) {
4405                 int sz = 4 - (sh->index & 3);
4406                 memset (sh->data + sh->index, 0, sz);
4407                 sh->index += sz;
4408         }
4409 }
4410
4411 struct StreamDesc {
4412         const char *name;
4413         MonoDynamicStream *stream;
4414 };
4415
4416 /*
4417  * build_compressed_metadata() fills in the blob of data that represents the 
4418  * raw metadata as it will be saved in the PE file. The five streams are output 
4419  * and the metadata tables are comnpressed from the guint32 array representation, 
4420  * to the compressed on-disk format.
4421  */
4422 static gboolean
4423 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4424 {
4425         MonoDynamicTable *table;
4426         int i;
4427         guint64 valid_mask = 0;
4428         guint64 sorted_mask;
4429         guint32 heapt_size = 0;
4430         guint32 meta_size = 256; /* allow for header and other stuff */
4431         guint32 table_offset;
4432         guint32 ntables = 0;
4433         guint64 *int64val;
4434         guint32 *int32val;
4435         guint16 *int16val;
4436         MonoImage *meta;
4437         unsigned char *p;
4438         struct StreamDesc stream_desc [5];
4439
4440         mono_error_init (error);
4441
4442         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4443         for (i = 0; i < assembly->gen_params->len; i++) {
4444                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4445                 if (!write_generic_param_entry (assembly, entry, error))
4446                         return FALSE;
4447         }
4448
4449         stream_desc [0].name  = "#~";
4450         stream_desc [0].stream = &assembly->tstream;
4451         stream_desc [1].name  = "#Strings";
4452         stream_desc [1].stream = &assembly->sheap;
4453         stream_desc [2].name  = "#US";
4454         stream_desc [2].stream = &assembly->us;
4455         stream_desc [3].name  = "#Blob";
4456         stream_desc [3].stream = &assembly->blob;
4457         stream_desc [4].name  = "#GUID";
4458         stream_desc [4].stream = &assembly->guid;
4459         
4460         /* tables that are sorted */
4461         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4462                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4463                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4464                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4465                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4466                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4467                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4468         
4469         /* Compute table sizes */
4470         /* the MonoImage has already been created in mono_image_basic_init() */
4471         meta = &assembly->image;
4472
4473         /* sizes should be multiple of 4 */
4474         pad_heap (&assembly->blob);
4475         pad_heap (&assembly->guid);
4476         pad_heap (&assembly->sheap);
4477         pad_heap (&assembly->us);
4478
4479         /* Setup the info used by compute_sizes () */
4480         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4481         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4482         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4483
4484         meta_size += assembly->blob.index;
4485         meta_size += assembly->guid.index;
4486         meta_size += assembly->sheap.index;
4487         meta_size += assembly->us.index;
4488
4489         for (i=0; i < MONO_TABLE_NUM; ++i)
4490                 meta->tables [i].rows = assembly->tables [i].rows;
4491         
4492         for (i = 0; i < MONO_TABLE_NUM; i++){
4493                 if (meta->tables [i].rows == 0)
4494                         continue;
4495                 valid_mask |= (guint64)1 << i;
4496                 ntables ++;
4497                 meta->tables [i].row_size = mono_metadata_compute_size (
4498                         meta, i, &meta->tables [i].size_bitfield);
4499                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4500         }
4501         heapt_size += 24; /* #~ header size */
4502         heapt_size += ntables * 4;
4503         /* make multiple of 4 */
4504         heapt_size += 3;
4505         heapt_size &= ~3;
4506         meta_size += heapt_size;
4507         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4508         p = (unsigned char*)meta->raw_metadata;
4509         /* the metadata signature */
4510         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4511         /* version numbers and 4 bytes reserved */
4512         int16val = (guint16*)p;
4513         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4514         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4515         p += 8;
4516         /* version string */
4517         int32val = (guint32*)p;
4518         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4519         p += 4;
4520         memcpy (p, meta->version, strlen (meta->version));
4521         p += GUINT32_FROM_LE (*int32val);
4522         align_pointer (meta->raw_metadata, p);
4523         int16val = (guint16*)p;
4524         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4525         *int16val = GUINT16_TO_LE (5); /* number of streams */
4526         p += 4;
4527
4528         /*
4529          * write the stream info.
4530          */
4531         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4532         table_offset += 3; table_offset &= ~3;
4533
4534         assembly->tstream.index = heapt_size;
4535         for (i = 0; i < 5; ++i) {
4536                 int32val = (guint32*)p;
4537                 stream_desc [i].stream->offset = table_offset;
4538                 *int32val++ = GUINT32_TO_LE (table_offset);
4539                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4540                 table_offset += GUINT32_FROM_LE (*int32val);
4541                 table_offset += 3; table_offset &= ~3;
4542                 p += 8;
4543                 strcpy ((char*)p, stream_desc [i].name);
4544                 p += strlen (stream_desc [i].name) + 1;
4545                 align_pointer (meta->raw_metadata, p);
4546         }
4547         /* 
4548          * now copy the data, the table stream header and contents goes first.
4549          */
4550         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4551         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4552         int32val = (guint32*)p;
4553         *int32val = GUINT32_TO_LE (0); /* reserved */
4554         p += 4;
4555
4556         *p++ = 2; /* version */
4557         *p++ = 0;
4558
4559         if (meta->idx_string_wide)
4560                 *p |= 0x01;
4561         if (meta->idx_guid_wide)
4562                 *p |= 0x02;
4563         if (meta->idx_blob_wide)
4564                 *p |= 0x04;
4565         ++p;
4566         *p++ = 1; /* reserved */
4567         int64val = (guint64*)p;
4568         *int64val++ = GUINT64_TO_LE (valid_mask);
4569         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4570         p += 16;
4571         int32val = (guint32*)p;
4572         for (i = 0; i < MONO_TABLE_NUM; i++){
4573                 if (meta->tables [i].rows == 0)
4574                         continue;
4575                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4576         }
4577         p = (unsigned char*)int32val;
4578
4579         /* sort the tables that still need sorting */
4580         table = &assembly->tables [MONO_TABLE_CONSTANT];
4581         if (table->rows)
4582                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4583         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4584         if (table->rows)
4585                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4586         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4587         if (table->rows)
4588                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4589         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4590         if (table->rows)
4591                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4592         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4593         if (table->rows)
4594                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4595         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4596         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4597         if (table->rows)
4598                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4599         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4600         if (table->rows)
4601                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4602
4603         /* compress the tables */
4604         for (i = 0; i < MONO_TABLE_NUM; i++){
4605                 int row, col;
4606                 guint32 *values;
4607                 guint32 bitfield = meta->tables [i].size_bitfield;
4608                 if (!meta->tables [i].rows)
4609                         continue;
4610                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4611                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4612                 meta->tables [i].base = (char*)p;
4613                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4614                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4615                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4616                                 switch (mono_metadata_table_size (bitfield, col)) {
4617                                 case 1:
4618                                         *p++ = values [col];
4619                                         break;
4620                                 case 2:
4621                                         *p++ = values [col] & 0xff;
4622                                         *p++ = (values [col] >> 8) & 0xff;
4623                                         break;
4624                                 case 4:
4625                                         *p++ = values [col] & 0xff;
4626                                         *p++ = (values [col] >> 8) & 0xff;
4627                                         *p++ = (values [col] >> 16) & 0xff;
4628                                         *p++ = (values [col] >> 24) & 0xff;
4629                                         break;
4630                                 default:
4631                                         g_assert_not_reached ();
4632                                 }
4633                         }
4634                 }
4635                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4636         }
4637         
4638         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4639         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4640         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4641         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4642         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4643
4644         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4645
4646         return TRUE;
4647 }
4648
4649 /*
4650  * Some tables in metadata need to be sorted according to some criteria, but
4651  * when methods and fields are first created with reflection, they may be assigned a token
4652  * that doesn't correspond to the final token they will get assigned after the sorting.
4653  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4654  * with the reflection objects that represent them. Once all the tables are set up, the 
4655  * reflection objects will contains the correct table index. fixup_method() will fixup the
4656  * tokens for the method with ILGenerator @ilgen.
4657  */
4658 static void
4659 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4660 {
4661         guint32 code_idx = GPOINTER_TO_UINT (value);
4662         MonoReflectionILTokenInfo *iltoken;
4663         MonoReflectionFieldBuilder *field;
4664         MonoReflectionCtorBuilder *ctor;
4665         MonoReflectionMethodBuilder *method;
4666         MonoReflectionTypeBuilder *tb;
4667         MonoReflectionArrayMethod *am;
4668         guint32 i, idx = 0;
4669         unsigned char *target;
4670
4671         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4672                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4673                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4674                 switch (target [3]) {
4675                 case MONO_TABLE_FIELD:
4676                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4677                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4678                                 idx = field->table_idx;
4679                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4680                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4681                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4682                         } else {
4683                                 g_assert_not_reached ();
4684                         }
4685                         break;
4686                 case MONO_TABLE_METHOD:
4687                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4688                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4689                                 idx = method->table_idx;
4690                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4691                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4692                                 idx = ctor->table_idx;
4693                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4694                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4695                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4696                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4697                         } else {
4698                                 g_assert_not_reached ();
4699                         }
4700                         break;
4701                 case MONO_TABLE_TYPEDEF:
4702                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4703                                 g_assert_not_reached ();
4704                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4705                         idx = tb->table_idx;
4706                         break;
4707                 case MONO_TABLE_MEMBERREF:
4708                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4709                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4710                                 idx = am->table_idx;
4711                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4712                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4713                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4714                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4715                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4716                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4717                                 continue;
4718                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4719                                 continue;
4720                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4721                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4722                                 g_assert (is_field_on_inst (f));
4723                                 continue;
4724                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4725                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4726                                 continue;
4727                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4728                                 continue;
4729                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4730                                 continue;
4731                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4732                                 continue;
4733                         } else {
4734                                 g_assert_not_reached ();
4735                         }
4736                         break;
4737                 case MONO_TABLE_METHODSPEC:
4738                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4739                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4740                                 g_assert (mono_method_signature (m)->generic_param_count);
4741                                 continue;
4742                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4743                                 continue;
4744                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4745                                 continue;
4746                         } else {
4747                                 g_assert_not_reached ();
4748                         }
4749                         break;
4750                 default:
4751                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4752                 }
4753                 target [0] = idx & 0xff;
4754                 target [1] = (idx >> 8) & 0xff;
4755                 target [2] = (idx >> 16) & 0xff;
4756         }
4757 }
4758
4759 /*
4760  * fixup_cattrs:
4761  *
4762  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4763  * value is not known when the table is emitted.
4764  */
4765 static void
4766 fixup_cattrs (MonoDynamicImage *assembly)
4767 {
4768         MonoDynamicTable *table;
4769         guint32 *values;
4770         guint32 type, i, idx, token;
4771         MonoObject *ctor;
4772
4773         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4774
4775         for (i = 0; i < table->rows; ++i) {
4776                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4777
4778                 type = values [MONO_CUSTOM_ATTR_TYPE];
4779                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4780                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4781                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4782                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4783                         g_assert (ctor);
4784
4785                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4786                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4787                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4788                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4789                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4790                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4791                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4792                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4793                         }
4794                 }
4795         }
4796 }
4797
4798 static void
4799 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4800 {
4801         MonoDynamicTable *table;
4802         guint32 *values;
4803
4804         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4805         table->rows++;
4806         alloc_table (table, table->rows);
4807         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4808         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4809         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4810         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4811         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4812         table->next_idx++;
4813 }
4814
4815 static void
4816 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4817 {
4818         MonoDynamicTable *table;
4819         guint32 *values;
4820         char blob_size [6];
4821         guchar hash [20];
4822         char *b = blob_size;
4823         char *name, *sname;
4824         guint32 idx, offset;
4825
4826         if (rsrc->filename) {
4827                 name = mono_string_to_utf8 (rsrc->filename);
4828                 sname = g_path_get_basename (name);
4829         
4830                 table = &assembly->tables [MONO_TABLE_FILE];
4831                 table->rows++;
4832                 alloc_table (table, table->rows);
4833                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4834                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4835                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4836                 g_free (sname);
4837
4838                 mono_sha1_get_digest_from_file (name, hash);
4839                 mono_metadata_encode_value (20, b, &b);
4840                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4841                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4842                 g_free (name);
4843                 idx = table->next_idx++;
4844                 rsrc->offset = 0;
4845                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4846         } else {
4847                 char sizebuf [4];
4848                 char *data;
4849                 guint len;
4850                 if (rsrc->data) {
4851                         data = mono_array_addr (rsrc->data, char, 0);
4852                         len = mono_array_length (rsrc->data);
4853                 } else {
4854                         data = NULL;
4855                         len = 0;
4856                 }
4857                 offset = len;
4858                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4859                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4860                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4861                 mono_image_add_stream_data (&assembly->resources, data, len);
4862
4863                 if (!mb->is_main)
4864                         /* 
4865                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4866                          * the main module, but that needs to reference the FILE table
4867                          * which isn't emitted yet.
4868                          */
4869                         return;
4870                 else
4871                         idx = 0;
4872         }
4873
4874         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4875 }
4876
4877 static void
4878 set_version_from_string (MonoString *version, guint32 *values)
4879 {
4880         gchar *ver, *p, *str;
4881         guint32 i;
4882         
4883         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4884         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4885         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4886         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4887         if (!version)
4888                 return;
4889         ver = str = mono_string_to_utf8 (version);
4890         for (i = 0; i < 4; ++i) {
4891                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4892                 switch (*p) {
4893                 case '.':
4894                         p++;
4895                         break;
4896                 case '*':
4897                         /* handle Revision and Build */
4898                         p++;
4899                         break;
4900                 }
4901                 ver = p;
4902         }
4903         g_free (str);
4904 }
4905
4906 static guint32
4907 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4908         gsize len;
4909         guint32 token = 0;
4910         char blob_size [6];
4911         char *b = blob_size;
4912
4913         if (!pkey)
4914                 return token;
4915
4916         len = mono_array_length (pkey);
4917         mono_metadata_encode_value (len, b, &b);
4918         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4919         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4920
4921         assembly->public_key = (guint8 *)g_malloc (len);
4922         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4923         assembly->public_key_len = len;
4924
4925         /* Special case: check for ECMA key (16 bytes) */
4926         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4927                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4928                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4929         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4930                 /* minimum key size (in 2.0) is 384 bits */
4931                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4932         } else {
4933                 /* FIXME - verifier */
4934                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4935                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4936         }
4937         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4938
4939         return token;
4940 }
4941
4942 static void
4943 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4944 {
4945         MonoDynamicTable *table;
4946         MonoDynamicImage *assembly;
4947         MonoReflectionAssemblyBuilder *assemblyb;
4948         MonoDomain *domain;
4949         guint32 *values;
4950         int i;
4951         guint32 module_index;
4952
4953         assemblyb = moduleb->assemblyb;
4954         assembly = moduleb->dynamic_image;
4955         domain = mono_object_domain (assemblyb);
4956
4957         /* Emit ASSEMBLY table */
4958         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4959         alloc_table (table, 1);
4960         values = table->values + MONO_ASSEMBLY_SIZE;
4961         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4962         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4963         if (assemblyb->culture) {
4964                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4965         } else {
4966                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4967         }
4968         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4969         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4970         set_version_from_string (assemblyb->version, values);
4971
4972         /* Emit FILE + EXPORTED_TYPE table */
4973         module_index = 0;
4974         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4975                 int j;
4976                 MonoReflectionModuleBuilder *file_module = 
4977                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4978                 if (file_module != moduleb) {
4979                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4980                         module_index ++;
4981                         if (file_module->types) {
4982                                 for (j = 0; j < file_module->num_types; ++j) {
4983                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4984                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4985                                 }
4986                         }
4987                 }
4988         }
4989         if (assemblyb->loaded_modules) {
4990                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4991                         MonoReflectionModule *file_module = 
4992                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4993                         mono_image_fill_file_table (domain, file_module, assembly);
4994                         module_index ++;
4995                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4996                 }
4997         }
4998         if (assemblyb->type_forwarders)
4999                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5000
5001         /* Emit MANIFESTRESOURCE table */
5002         module_index = 0;
5003         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5004                 int j;
5005                 MonoReflectionModuleBuilder *file_module = 
5006                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5007                 /* The table for the main module is emitted later */
5008                 if (file_module != moduleb) {
5009                         module_index ++;
5010                         if (file_module->resources) {
5011                                 int len = mono_array_length (file_module->resources);
5012                                 for (j = 0; j < len; ++j) {
5013                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5014                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5015                                 }
5016                         }
5017                 }
5018         }               
5019 }
5020
5021 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5022
5023 /*
5024  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5025  * for the modulebuilder @moduleb.
5026  * At the end of the process, method and field tokens are fixed up and the 
5027  * on-disk compressed metadata representation is created.
5028  * Return TRUE on success, or FALSE on failure and sets @error
5029  */
5030 gboolean
5031 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5032 {
5033         MonoDynamicTable *table;
5034         MonoDynamicImage *assembly;
5035         MonoReflectionAssemblyBuilder *assemblyb;
5036         MonoDomain *domain;
5037         MonoPtrArray types;
5038         guint32 *values;
5039         int i, j;
5040
5041         mono_error_init (error);
5042
5043         assemblyb = moduleb->assemblyb;
5044         assembly = moduleb->dynamic_image;
5045         domain = mono_object_domain (assemblyb);
5046
5047         if (assembly->text_rva)
5048                 return TRUE;
5049
5050         assembly->text_rva = START_TEXT_RVA;
5051
5052         if (moduleb->is_main) {
5053                 mono_image_emit_manifest (moduleb);
5054         }
5055
5056         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5057         table->rows = 1; /* .<Module> */
5058         table->next_idx++;
5059         alloc_table (table, table->rows);
5060         /*
5061          * Set the first entry.
5062          */
5063         values = table->values + table->columns;
5064         values [MONO_TYPEDEF_FLAGS] = 0;
5065         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5066         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5067         values [MONO_TYPEDEF_EXTENDS] = 0;
5068         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5069         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5070
5071         /* 
5072          * handle global methods 
5073          * FIXME: test what to do when global methods are defined in multiple modules.
5074          */
5075         if (moduleb->global_methods) {
5076                 table = &assembly->tables [MONO_TABLE_METHOD];
5077                 table->rows += mono_array_length (moduleb->global_methods);
5078                 alloc_table (table, table->rows);
5079                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5080                         if (!mono_image_get_method_info (
5081                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5082                                 goto leave;
5083                 }
5084         }
5085         if (moduleb->global_fields) {
5086                 table = &assembly->tables [MONO_TABLE_FIELD];
5087                 table->rows += mono_array_length (moduleb->global_fields);
5088                 alloc_table (table, table->rows);
5089                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
5090                         mono_image_get_field_info (
5091                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
5092         }
5093
5094         table = &assembly->tables [MONO_TABLE_MODULE];
5095         alloc_table (table, 1);
5096         mono_image_fill_module_table (domain, moduleb, assembly);
5097
5098         /* Collect all types into a list sorted by their table_idx */
5099         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5100
5101         if (moduleb->types)
5102                 for (i = 0; i < moduleb->num_types; ++i) {
5103                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5104                         collect_types (&types, type);
5105                 }
5106
5107         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5108         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5109         table->rows += mono_ptr_array_size (types);
5110         alloc_table (table, table->rows);
5111
5112         /*
5113          * Emit type names + namespaces at one place inside the string heap,
5114          * so load_class_names () needs to touch fewer pages.
5115          */
5116         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5117                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5118                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5119         }
5120         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5121                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5122                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5123         }
5124
5125         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5126                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5127                 if (!mono_image_get_type_info (domain, type, assembly, error))
5128                         goto leave_types;
5129         }
5130
5131         /* 
5132          * table->rows is already set above and in mono_image_fill_module_table.
5133          */
5134         /* add all the custom attributes at the end, once all the indexes are stable */
5135         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5136                 goto leave_types;
5137
5138         /* CAS assembly permissions */
5139         if (assemblyb->permissions_minimum)
5140                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5141         if (assemblyb->permissions_optional)
5142                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5143         if (assemblyb->permissions_refused)
5144                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5145
5146         if (!module_add_cattrs (assembly, moduleb, error))
5147                 goto leave_types;
5148
5149         /* fixup tokens */
5150         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5151
5152         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5153          * the final tokens and don't need another fixup pass. */
5154
5155         if (moduleb->global_methods) {
5156                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5157                         MonoReflectionMethodBuilder *mb = mono_array_get (
5158                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5159                         if (!mono_image_add_methodimpl (assembly, mb, error))
5160                                 goto leave_types;
5161                 }
5162         }
5163
5164         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5165                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5166                 if (type->methods) {
5167                         for (j = 0; j < type->num_methods; ++j) {
5168                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5169                                         type->methods, MonoReflectionMethodBuilder*, j);
5170
5171                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5172                                         goto leave_types;
5173                         }
5174                 }
5175         }
5176
5177         fixup_cattrs (assembly);
5178
5179 leave_types:
5180         mono_ptr_array_destroy (types);
5181 leave:
5182
5183         return mono_error_ok (error);
5184 }
5185
5186 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5187
5188 gboolean
5189 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5190 {
5191         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5192 }
5193
5194 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5195
5196
5197 typedef struct {
5198         guint32 import_lookup_table;
5199         guint32 timestamp;
5200         guint32 forwarder;
5201         guint32 name_rva;
5202         guint32 import_address_table_rva;
5203 } MonoIDT;
5204
5205 typedef struct {
5206         guint32 name_rva;
5207         guint32 flags;
5208 } MonoILT;
5209
5210 #ifndef DISABLE_REFLECTION_EMIT
5211
5212 /*
5213  * mono_image_insert_string:
5214  * @module: module builder object
5215  * @str: a string
5216  *
5217  * Insert @str into the user string stream of @module.
5218  */
5219 guint32
5220 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5221 {
5222         MonoDynamicImage *assembly;
5223         guint32 idx;
5224         char buf [16];
5225         char *b = buf;
5226         
5227         if (!module->dynamic_image)
5228                 mono_image_module_basic_init (module);
5229
5230         assembly = module->dynamic_image;
5231         
5232         if (assembly->save) {
5233                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5234                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5235 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5236         {
5237                 char *swapped = g_malloc (2 * mono_string_length (str));
5238                 const char *p = (const char*)mono_string_chars (str);
5239
5240                 swap_with_size (swapped, p, 2, mono_string_length (str));
5241                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5242                 g_free (swapped);
5243         }
5244 #else
5245                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5246 #endif
5247                 mono_image_add_stream_data (&assembly->us, "", 1);
5248         } else {
5249                 idx = assembly->us.index ++;
5250         }
5251
5252         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5253
5254         return MONO_TOKEN_STRING | idx;
5255 }
5256
5257 guint32
5258 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5259 {
5260         MonoClass *klass;
5261         guint32 token = 0;
5262         MonoMethodSignature *sig;
5263
5264         mono_error_init (error);
5265
5266         klass = obj->vtable->klass;
5267         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5268                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5269                 MonoMethodSignature *old;
5270                 guint32 sig_token, parent;
5271                 int nargs, i;
5272
5273                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5274
5275                 nargs = mono_array_length (opt_param_types);
5276                 old = mono_method_signature (method);
5277                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5278
5279                 sig->hasthis = old->hasthis;
5280                 sig->explicit_this = old->explicit_this;
5281                 sig->call_convention = old->call_convention;
5282                 sig->generic_param_count = old->generic_param_count;
5283                 sig->param_count = old->param_count + nargs;
5284                 sig->sentinelpos = old->param_count;
5285                 sig->ret = old->ret;
5286
5287                 for (i = 0; i < old->param_count; i++)
5288                         sig->params [i] = old->params [i];
5289
5290                 for (i = 0; i < nargs; i++) {
5291                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5292                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5293                         if (!is_ok (error)) goto fail;
5294                 }
5295
5296                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5297                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5298                 parent >>= MONO_TYPEDEFORREF_BITS;
5299
5300                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5301                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5302
5303                 sig_token = method_encode_signature (assembly, sig);
5304                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5305         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5306                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5307                 ReflectionMethodBuilder rmb;
5308                 guint32 parent, sig_token;
5309                 int nopt_args, nparams, ngparams, i;
5310
5311                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5312                         goto fail;
5313                 
5314                 rmb.opt_types = opt_param_types;
5315                 nopt_args = mono_array_length (opt_param_types);
5316
5317                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5318                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5319                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5320
5321                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5322                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5323                 sig->call_convention = rmb.call_conv;
5324                 sig->generic_param_count = ngparams;
5325                 sig->param_count = nparams + nopt_args;
5326                 sig->sentinelpos = nparams;
5327                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5328                 if (!is_ok (error)) goto fail;
5329
5330                 for (i = 0; i < nparams; i++) {
5331                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5332                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5333                         if (!is_ok (error)) goto fail;
5334                 }
5335
5336                 for (i = 0; i < nopt_args; i++) {
5337                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5338                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5339                         if (!is_ok (error)) goto fail;
5340                 }
5341
5342                 sig_token = method_builder_encode_signature (assembly, &rmb);
5343
5344                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5345                 if (!mono_error_ok (error))
5346                         goto fail;
5347                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5348
5349                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5350                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5351
5352                 char *name = mono_string_to_utf8 (rmb.name);
5353                 token = mono_image_get_varargs_method_token (
5354                         assembly, parent, name, sig_token);
5355                 g_free (name);
5356         } else {
5357                 g_error ("requested method token for %s\n", klass->name);
5358         }
5359
5360         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5361         register_dyn_token (assembly, token, obj);
5362         return token;
5363 fail:
5364         g_assert (!mono_error_ok (error));
5365         return 0;
5366 }
5367
5368 /*
5369  * mono_image_create_token:
5370  * @assembly: a dynamic assembly
5371  * @obj:
5372  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5373  *
5374  * Get a token to insert in the IL code stream for the given MemberInfo.
5375  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5376  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5377  * entry.
5378  */
5379 guint32
5380 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5381                          gboolean create_open_instance, gboolean register_token,
5382                          MonoError *error)
5383 {
5384         MonoClass *klass;
5385         guint32 token = 0;
5386
5387         mono_error_init (error);
5388
5389         klass = obj->vtable->klass;
5390
5391         /* Check for user defined reflection objects */
5392         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5393         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5394                 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5395                 return 0;
5396         }
5397
5398         if (strcmp (klass->name, "MethodBuilder") == 0) {
5399                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5400                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5401
5402                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5403                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5404                 else {
5405                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5406                         if (!mono_error_ok (error))
5407                                 return 0;
5408                 }
5409                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5410         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5411                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5412                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5413
5414                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5415                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5416                 else {
5417                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5418                         if (!mono_error_ok (error))
5419                                 return 0;
5420                 }
5421                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5422         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5423                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5424                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5425                 if (tb->generic_params) {
5426                         token = mono_image_get_generic_field_token (assembly, fb);
5427                 } else {
5428                         if (tb->module->dynamic_image == assembly) {
5429                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5430                         } else {
5431                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5432                         }
5433                 }
5434         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5435                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5436                 if (create_open_instance && tb->generic_params) {
5437                         MonoType *type;
5438                         init_type_builder_generics (obj);
5439                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5440                         return_val_if_nok (error, 0);
5441                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5442                         token = mono_metadata_token_from_dor (token);
5443                 } else if (tb->module->dynamic_image == assembly) {
5444                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5445                 } else {
5446                         MonoType *type;
5447                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5448                         return_val_if_nok (error, 0);
5449                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5450                 }
5451         } else if (strcmp (klass->name, "MonoType") == 0) {
5452                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5453                 return_val_if_nok (error, 0);
5454                 MonoClass *mc = mono_class_from_mono_type (type);
5455                 token = mono_metadata_token_from_dor (
5456                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5457         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5458                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5459                 return_val_if_nok (error, 0);
5460                 token = mono_metadata_token_from_dor (
5461                         mono_image_typedef_or_ref (assembly, type));
5462         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5463                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5464                 return_val_if_nok (error, 0);
5465                 token = mono_metadata_token_from_dor (
5466                         mono_image_typedef_or_ref (assembly, type));
5467         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5468                    strcmp (klass->name, "MonoMethod") == 0 ||
5469                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5470                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5471                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5472                 if (m->method->is_inflated) {
5473                         if (create_open_instance)
5474                                 token = mono_image_get_methodspec_token (assembly, m->method);
5475                         else
5476                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5477                 } else if ((m->method->klass->image == &assembly->image) &&
5478                          !m->method->klass->generic_class) {
5479                         static guint32 method_table_idx = 0xffffff;
5480                         if (m->method->klass->wastypebuilder) {
5481                                 /* we use the same token as the one that was assigned
5482                                  * to the Methodbuilder.
5483                                  * FIXME: do the equivalent for Fields.
5484                                  */
5485                                 token = m->method->token;
5486                         } else {
5487                                 /*
5488                                  * Each token should have a unique index, but the indexes are
5489                                  * assigned by managed code, so we don't know about them. An
5490                                  * easy solution is to count backwards...
5491                                  */
5492                                 method_table_idx --;
5493                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5494                         }
5495                 } else {
5496                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5497                 }
5498                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5499         } else if (strcmp (klass->name, "MonoField") == 0) {
5500                 MonoReflectionField *f = (MonoReflectionField *)obj;
5501                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5502                         static guint32 field_table_idx = 0xffffff;
5503                         field_table_idx --;
5504                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5505                 } else {
5506                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5507                 }
5508                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5509         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5510                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5511                 token = mono_image_get_array_token (assembly, m);
5512         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5513                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5514                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5515         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5516                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5517                 return_val_if_nok (error, 0);
5518                 token = mono_metadata_token_from_dor (
5519                         mono_image_typedef_or_ref (assembly, type));
5520         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5521                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5522                 token = mono_image_get_field_on_inst_token (assembly, f);
5523         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5524                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5525                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5526                 if (!mono_error_ok (error))
5527                         return 0;
5528         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5529                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5530                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5531                 if (!mono_error_ok (error))
5532                         return 0;
5533         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5534                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5535                 return_val_if_nok (error, 0);
5536                 token = mono_metadata_token_from_dor (
5537                                 mono_image_typedef_or_ref (assembly, type));
5538         } else {
5539                 g_error ("requested token for %s\n", klass->name);
5540         }
5541
5542         if (register_token)
5543                 mono_image_register_token (assembly, token, obj);
5544
5545         return token;
5546 }
5547
5548 /*
5549  * mono_image_register_token:
5550  *
5551  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5552  * the Module.ResolveXXXToken () methods to work.
5553  */
5554 void
5555 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5556 {
5557         MonoObject *prev;
5558
5559         dynamic_image_lock (assembly);
5560         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5561         if (prev) {
5562                 /* There could be multiple MethodInfo objects with the same token */
5563                 //g_assert (prev == obj);
5564         } else {
5565                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5566         }
5567         dynamic_image_unlock (assembly);
5568 }
5569
5570 static MonoDynamicImage*
5571 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5572 {
5573         static const guchar entrycode [16] = {0xff, 0x25, 0};
5574         MonoDynamicImage *image;
5575         int i;
5576
5577         const char *version;
5578
5579         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5580                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5581         else
5582                 version = mono_get_runtime_info ()->runtime_version;
5583
5584 #if HAVE_BOEHM_GC
5585         /* The MonoGHashTable's need GC tracking */
5586         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5587 #else
5588         image = g_new0 (MonoDynamicImage, 1);
5589 #endif
5590
5591         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5592         
5593         /*g_print ("created image %p\n", image);*/
5594         /* keep in sync with image.c */
5595         image->image.name = assembly_name;
5596         image->image.assembly_name = image->image.name; /* they may be different */
5597         image->image.module_name = module_name;
5598         image->image.version = g_strdup (version);
5599         image->image.md_version_major = 1;
5600         image->image.md_version_minor = 1;
5601         image->image.dynamic = TRUE;
5602
5603         image->image.references = g_new0 (MonoAssembly*, 1);
5604         image->image.references [0] = NULL;
5605
5606         mono_image_init (&image->image);
5607
5608         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");
5609         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5610         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5611         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5612         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5613         image->handleref = g_hash_table_new (NULL, NULL);
5614         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");
5615         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5616         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");
5617         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");
5618         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5619         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5620         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5621         image->gen_params = g_ptr_array_new ();
5622         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5623
5624         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5625         string_heap_init (&image->sheap);
5626         mono_image_add_stream_data (&image->us, "", 1);
5627         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5628         /* import tables... */
5629         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5630         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5631         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5632         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5633         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5634         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5635         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5636         stream_data_align (&image->code);
5637
5638         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5639
5640         for (i=0; i < MONO_TABLE_NUM; ++i) {
5641                 image->tables [i].next_idx = 1;
5642                 image->tables [i].columns = table_sizes [i];
5643         }
5644
5645         image->image.assembly = (MonoAssembly*)assembly;
5646         image->run = assembly->run;
5647         image->save = assembly->save;
5648         image->pe_kind = 0x1; /* ILOnly */
5649         image->machine = 0x14c; /* I386 */
5650         
5651         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5652
5653         dynamic_images_lock ();
5654
5655         if (!dynamic_images)
5656                 dynamic_images = g_ptr_array_new ();
5657
5658         g_ptr_array_add (dynamic_images, image);
5659
5660         dynamic_images_unlock ();
5661
5662         return image;
5663 }
5664 #endif
5665
5666 static void
5667 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5668 {
5669         g_free (key);
5670 }
5671
5672 static void
5673 release_hashtable (MonoGHashTable **hash)
5674 {
5675         if (*hash) {
5676                 mono_g_hash_table_destroy (*hash);
5677                 *hash = NULL;
5678         }
5679 }
5680
5681 void
5682 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5683 {
5684         release_hashtable (&image->token_fixups);
5685         release_hashtable (&image->handleref_managed);
5686         release_hashtable (&image->tokens);
5687         release_hashtable (&image->remapped_tokens);
5688         release_hashtable (&image->generic_def_objects);
5689         release_hashtable (&image->methodspec);
5690 }
5691
5692 // Free dynamic image pass one: Free resources but not image itself
5693 void
5694 mono_dynamic_image_free (MonoDynamicImage *image)
5695 {
5696         MonoDynamicImage *di = image;
5697         GList *list;
5698         int i;
5699
5700         if (di->methodspec)
5701                 mono_g_hash_table_destroy (di->methodspec);
5702         if (di->typespec)
5703                 g_hash_table_destroy (di->typespec);
5704         if (di->typeref)
5705                 g_hash_table_destroy (di->typeref);
5706         if (di->handleref)
5707                 g_hash_table_destroy (di->handleref);
5708         if (di->handleref_managed)
5709                 mono_g_hash_table_destroy (di->handleref_managed);
5710         if (di->tokens)
5711                 mono_g_hash_table_destroy (di->tokens);
5712         if (di->remapped_tokens)
5713                 mono_g_hash_table_destroy (di->remapped_tokens);
5714         if (di->generic_def_objects)
5715                 mono_g_hash_table_destroy (di->generic_def_objects);
5716         if (di->blob_cache) {
5717                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5718                 g_hash_table_destroy (di->blob_cache);
5719         }
5720         if (di->standalonesig_cache)
5721                 g_hash_table_destroy (di->standalonesig_cache);
5722         for (list = di->array_methods; list; list = list->next) {
5723                 ArrayMethod *am = (ArrayMethod *)list->data;
5724                 g_free (am->sig);
5725                 g_free (am->name);
5726                 g_free (am);
5727         }
5728         g_list_free (di->array_methods);
5729         if (di->gen_params) {
5730                 for (i = 0; i < di->gen_params->len; i++) {
5731                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5732                         mono_gc_deregister_root ((char*) &entry->gparam);
5733                         g_free (entry);
5734                 }
5735                 g_ptr_array_free (di->gen_params, TRUE);
5736         }
5737         if (di->token_fixups)
5738                 mono_g_hash_table_destroy (di->token_fixups);
5739         if (di->method_to_table_idx)
5740                 g_hash_table_destroy (di->method_to_table_idx);
5741         if (di->field_to_table_idx)
5742                 g_hash_table_destroy (di->field_to_table_idx);
5743         if (di->method_aux_hash)
5744                 g_hash_table_destroy (di->method_aux_hash);
5745         if (di->vararg_aux_hash)
5746                 g_hash_table_destroy (di->vararg_aux_hash);
5747         g_free (di->strong_name);
5748         g_free (di->win32_res);
5749         if (di->public_key)
5750                 g_free (di->public_key);
5751
5752         /*g_print ("string heap destroy for image %p\n", di);*/
5753         mono_dynamic_stream_reset (&di->sheap);
5754         mono_dynamic_stream_reset (&di->code);
5755         mono_dynamic_stream_reset (&di->resources);
5756         mono_dynamic_stream_reset (&di->us);
5757         mono_dynamic_stream_reset (&di->blob);
5758         mono_dynamic_stream_reset (&di->tstream);
5759         mono_dynamic_stream_reset (&di->guid);
5760         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5761                 g_free (di->tables [i].values);
5762         }
5763
5764         dynamic_images_lock ();
5765
5766         if (dynamic_images)
5767                 g_ptr_array_remove (dynamic_images, di);
5768
5769         dynamic_images_unlock ();
5770 }
5771
5772 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5773 void
5774 mono_dynamic_image_free_image (MonoDynamicImage *image)
5775 {
5776         /* See create_dynamic_mono_image () */
5777 #if HAVE_BOEHM_GC
5778         /* Allocated using GC_MALLOC */
5779 #else
5780         g_free (image);
5781 #endif
5782 }
5783
5784 #ifndef DISABLE_REFLECTION_EMIT
5785
5786 /*
5787  * mono_image_basic_init:
5788  * @assembly: an assembly builder object
5789  *
5790  * Create the MonoImage that represents the assembly builder and setup some
5791  * of the helper hash table and the basic metadata streams.
5792  */
5793 void
5794 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5795 {
5796         MonoDynamicAssembly *assembly;
5797         MonoDynamicImage *image;
5798         MonoDomain *domain = mono_object_domain (assemblyb);
5799         
5800         if (assemblyb->dynamic_assembly)
5801                 return;
5802
5803 #if HAVE_BOEHM_GC
5804         /* assembly->assembly.image might be GC allocated */
5805         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5806 #else
5807         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5808 #endif
5809
5810         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5811         
5812         assembly->assembly.ref_count = 1;
5813         assembly->assembly.dynamic = TRUE;
5814         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5815         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5816         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5817         if (assemblyb->culture)
5818                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5819         else
5820                 assembly->assembly.aname.culture = g_strdup ("");
5821
5822         if (assemblyb->version) {
5823                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5824                         char **version = g_strsplit (vstr, ".", 4);
5825                         char **parts = version;
5826                         assembly->assembly.aname.major = atoi (*parts++);
5827                         assembly->assembly.aname.minor = atoi (*parts++);
5828                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5829                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5830
5831                         g_strfreev (version);
5832                         g_free (vstr);
5833         } else {
5834                         assembly->assembly.aname.major = 0;
5835                         assembly->assembly.aname.minor = 0;
5836                         assembly->assembly.aname.build = 0;
5837                         assembly->assembly.aname.revision = 0;
5838         }
5839
5840         assembly->run = assemblyb->access != 2;
5841         assembly->save = assemblyb->access != 1;
5842         assembly->domain = domain;
5843
5844         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5845         image->initial_image = TRUE;
5846         assembly->assembly.aname.name = image->image.name;
5847         assembly->assembly.image = &image->image;
5848         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5849                 /* -1 to correct for the trailing NULL byte */
5850                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5851                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5852                 }
5853                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5854         }
5855
5856         mono_domain_assemblies_lock (domain);
5857         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5858         mono_domain_assemblies_unlock (domain);
5859
5860         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5861         
5862         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5863         
5864         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5865 }
5866
5867 #endif /* !DISABLE_REFLECTION_EMIT */
5868
5869 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5870
5871 static int
5872 calc_section_size (MonoDynamicImage *assembly)
5873 {
5874         int nsections = 0;
5875
5876         /* alignment constraints */
5877         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5878         g_assert ((assembly->code.index % 4) == 0);
5879         assembly->meta_size += 3;
5880         assembly->meta_size &= ~3;
5881         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5882         g_assert ((assembly->resources.index % 4) == 0);
5883
5884         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5885         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5886         nsections++;
5887
5888         if (assembly->win32_res) {
5889                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5890
5891                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5892                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5893                 nsections++;
5894         }
5895
5896         assembly->sections [MONO_SECTION_RELOC].size = 12;
5897         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5898         nsections++;
5899
5900         return nsections;
5901 }
5902
5903 typedef struct {
5904         guint32 id;
5905         guint32 offset;
5906         GSList *children;
5907         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5908 } ResTreeNode;
5909
5910 static int
5911 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5912 {
5913         ResTreeNode *t1 = (ResTreeNode*)a;
5914         ResTreeNode *t2 = (ResTreeNode*)b;
5915
5916         return t1->id - t2->id;
5917 }
5918
5919 /*
5920  * resource_tree_create:
5921  *
5922  *  Organize the resources into a resource tree.
5923  */
5924 static ResTreeNode *
5925 resource_tree_create (MonoArray *win32_resources)
5926 {
5927         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5928         GSList *l;
5929         int i;
5930
5931         tree = g_new0 (ResTreeNode, 1);
5932         
5933         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5934                 MonoReflectionWin32Resource *win32_res =
5935                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5936
5937                 /* Create node */
5938
5939                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5940                 lang_node = g_new0 (ResTreeNode, 1);
5941                 lang_node->id = win32_res->lang_id;
5942                 lang_node->win32_res = win32_res;
5943
5944                 /* Create type node if neccesary */
5945                 type_node = NULL;
5946                 for (l = tree->children; l; l = l->next)
5947                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5948                                 type_node = (ResTreeNode*)l->data;
5949                                 break;
5950                         }
5951
5952                 if (!type_node) {
5953                         type_node = g_new0 (ResTreeNode, 1);
5954                         type_node->id = win32_res->res_type;
5955
5956                         /* 
5957                          * The resource types have to be sorted otherwise
5958                          * Windows Explorer can't display the version information.
5959                          */
5960                         tree->children = g_slist_insert_sorted (tree->children, 
5961                                 type_node, resource_tree_compare_by_id);
5962                 }
5963
5964                 /* Create res node if neccesary */
5965                 res_node = NULL;
5966                 for (l = type_node->children; l; l = l->next)
5967                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5968                                 res_node = (ResTreeNode*)l->data;
5969                                 break;
5970                         }
5971
5972                 if (!res_node) {
5973                         res_node = g_new0 (ResTreeNode, 1);
5974                         res_node->id = win32_res->res_id;
5975                         type_node->children = g_slist_append (type_node->children, res_node);
5976                 }
5977
5978                 res_node->children = g_slist_append (res_node->children, lang_node);
5979         }
5980
5981         return tree;
5982 }
5983
5984 /*
5985  * resource_tree_encode:
5986  * 
5987  *   Encode the resource tree into the format used in the PE file.
5988  */
5989 static void
5990 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5991 {
5992         char *entries;
5993         MonoPEResourceDir dir;
5994         MonoPEResourceDirEntry dir_entry;
5995         MonoPEResourceDataEntry data_entry;
5996         GSList *l;
5997         guint32 res_id_entries;
5998
5999         /*
6000          * For the format of the resource directory, see the article
6001          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6002          * Matt Pietrek
6003          */
6004
6005         memset (&dir, 0, sizeof (dir));
6006         memset (&dir_entry, 0, sizeof (dir_entry));
6007         memset (&data_entry, 0, sizeof (data_entry));
6008
6009         g_assert (sizeof (dir) == 16);
6010         g_assert (sizeof (dir_entry) == 8);
6011         g_assert (sizeof (data_entry) == 16);
6012
6013         node->offset = p - begin;
6014
6015         /* IMAGE_RESOURCE_DIRECTORY */
6016         res_id_entries = g_slist_length (node->children);
6017         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6018
6019         memcpy (p, &dir, sizeof (dir));
6020         p += sizeof (dir);
6021
6022         /* Reserve space for entries */
6023         entries = p;
6024         p += sizeof (dir_entry) * res_id_entries;
6025
6026         /* Write children */
6027         for (l = node->children; l; l = l->next) {
6028                 ResTreeNode *child = (ResTreeNode*)l->data;
6029
6030                 if (child->win32_res) {
6031                         guint32 size;
6032
6033                         child->offset = p - begin;
6034
6035                         /* IMAGE_RESOURCE_DATA_ENTRY */
6036                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6037                         size = mono_array_length (child->win32_res->res_data);
6038                         data_entry.rde_size = GUINT32_TO_LE (size);
6039
6040                         memcpy (p, &data_entry, sizeof (data_entry));
6041                         p += sizeof (data_entry);
6042
6043                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6044                         p += size;
6045                 } else {
6046                         resource_tree_encode (child, begin, p, &p);
6047                 }
6048         }
6049
6050         /* IMAGE_RESOURCE_ENTRY */
6051         for (l = node->children; l; l = l->next) {
6052                 ResTreeNode *child = (ResTreeNode*)l->data;
6053
6054                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6055                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6056
6057                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6058                 entries += sizeof (dir_entry);
6059         }
6060
6061         *endbuf = p;
6062 }
6063
6064 static void
6065 resource_tree_free (ResTreeNode * node)
6066 {
6067         GSList * list;
6068         for (list = node->children; list; list = list->next)
6069                 resource_tree_free ((ResTreeNode*)list->data);
6070         g_slist_free(node->children);
6071         g_free (node);
6072 }
6073
6074 static void
6075 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6076 {
6077         char *buf;
6078         char *p;
6079         guint32 size, i;
6080         MonoReflectionWin32Resource *win32_res;
6081         ResTreeNode *tree;
6082
6083         if (!assemblyb->win32_resources)
6084                 return;
6085
6086         /*
6087          * Resources are stored in a three level tree inside the PE file.
6088          * - level one contains a node for each type of resource
6089          * - level two contains a node for each resource
6090          * - level three contains a node for each instance of a resource for a
6091          *   specific language.
6092          */
6093
6094         tree = resource_tree_create (assemblyb->win32_resources);
6095
6096         /* Estimate the size of the encoded tree */
6097         size = 0;
6098         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6099                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6100                 size += mono_array_length (win32_res->res_data);
6101         }
6102         /* Directory structure */
6103         size += mono_array_length (assemblyb->win32_resources) * 256;
6104         p = buf = (char *)g_malloc (size);
6105
6106         resource_tree_encode (tree, p, p, &p);
6107
6108         g_assert (p - buf <= size);
6109
6110         assembly->win32_res = (char *)g_malloc (p - buf);
6111         assembly->win32_res_size = p - buf;
6112         memcpy (assembly->win32_res, buf, p - buf);
6113
6114         g_free (buf);
6115         resource_tree_free (tree);
6116 }
6117
6118 static void
6119 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6120 {
6121         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6122         int i;
6123
6124         p += sizeof (MonoPEResourceDir);
6125         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6126                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6127                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6128                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6129                         fixup_resource_directory (res_section, child, rva);
6130                 } else {
6131                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6132                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6133                 }
6134
6135                 p += sizeof (MonoPEResourceDirEntry);
6136         }
6137 }
6138
6139 static void
6140 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6141 {
6142         guint32 dummy;
6143         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6144                 g_error ("WriteFile returned %d\n", GetLastError ());
6145 }
6146
6147 /*
6148  * mono_image_create_pefile:
6149  * @mb: a module builder object
6150  * 
6151  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6152  * assembly->pefile where it can be easily retrieved later in chunks.
6153  */
6154 gboolean
6155 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6156 {
6157         MonoMSDOSHeader *msdos;
6158         MonoDotNetHeader *header;
6159         MonoSectionTable *section;
6160         MonoCLIHeader *cli_header;
6161         guint32 size, image_size, virtual_base, text_offset;
6162         guint32 header_start, section_start, file_offset, virtual_offset;
6163         MonoDynamicImage *assembly;
6164         MonoReflectionAssemblyBuilder *assemblyb;
6165         MonoDynamicStream pefile_stream = {0};
6166         MonoDynamicStream *pefile = &pefile_stream;
6167         int i, nsections;
6168         guint32 *rva, value;
6169         guchar *p;
6170         static const unsigned char msheader[] = {
6171                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6172                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6173                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6174                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6175                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6176                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6177                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6178                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6179         };
6180
6181         mono_error_init (error);
6182
6183         assemblyb = mb->assemblyb;
6184
6185         mono_image_basic_init (assemblyb);
6186         assembly = mb->dynamic_image;
6187
6188         assembly->pe_kind = assemblyb->pe_kind;
6189         assembly->machine = assemblyb->machine;
6190         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6191         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6192         
6193         if (!mono_image_build_metadata (mb, error))
6194                 return FALSE;
6195         
6196
6197         if (mb->is_main && assemblyb->resources) {
6198                 int len = mono_array_length (assemblyb->resources);
6199                 for (i = 0; i < len; ++i)
6200                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6201         }
6202
6203         if (mb->resources) {
6204                 int len = mono_array_length (mb->resources);
6205                 for (i = 0; i < len; ++i)
6206                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6207         }
6208
6209         if (!build_compressed_metadata (assembly, error))
6210                 return FALSE;
6211
6212         if (mb->is_main)
6213                 assembly_add_win32_resources (assembly, assemblyb);
6214
6215         nsections = calc_section_size (assembly);
6216         
6217         /* The DOS header and stub */
6218         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6219         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6220
6221         /* the dotnet header */
6222         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6223
6224         /* the section tables */
6225         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6226
6227         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6228         virtual_offset = VIRT_ALIGN;
6229         image_size = 0;
6230
6231         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6232                 if (!assembly->sections [i].size)
6233                         continue;
6234                 /* align offsets */
6235                 file_offset += FILE_ALIGN - 1;
6236                 file_offset &= ~(FILE_ALIGN - 1);
6237                 virtual_offset += VIRT_ALIGN - 1;
6238                 virtual_offset &= ~(VIRT_ALIGN - 1);
6239
6240                 assembly->sections [i].offset = file_offset;
6241                 assembly->sections [i].rva = virtual_offset;
6242
6243                 file_offset += assembly->sections [i].size;
6244                 virtual_offset += assembly->sections [i].size;
6245                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6246         }
6247
6248         file_offset += FILE_ALIGN - 1;
6249         file_offset &= ~(FILE_ALIGN - 1);
6250
6251         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6252
6253         /* back-patch info */
6254         msdos = (MonoMSDOSHeader*)pefile->data;
6255         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6256
6257         header = (MonoDotNetHeader*)(pefile->data + header_start);
6258         header->pesig [0] = 'P';
6259         header->pesig [1] = 'E';
6260         
6261         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6262         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6263         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6264         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6265         if (assemblyb->pekind == 1) {
6266                 /* it's a dll */
6267                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6268         } else {
6269                 /* it's an exe */
6270                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6271         }
6272
6273         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6274
6275         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6276         header->pe.pe_major = 6;
6277         header->pe.pe_minor = 0;
6278         size = assembly->sections [MONO_SECTION_TEXT].size;
6279         size += FILE_ALIGN - 1;
6280         size &= ~(FILE_ALIGN - 1);
6281         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6282         size = assembly->sections [MONO_SECTION_RSRC].size;
6283         size += FILE_ALIGN - 1;
6284         size &= ~(FILE_ALIGN - 1);
6285         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6286         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6287         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6288         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6289         /* pe_rva_entry_point always at the beginning of the text section */
6290         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6291
6292         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6293         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6294         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6295         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6296         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6297         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6298         size = section_start;
6299         size += FILE_ALIGN - 1;
6300         size &= ~(FILE_ALIGN - 1);
6301         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6302         size = image_size;
6303         size += VIRT_ALIGN - 1;
6304         size &= ~(VIRT_ALIGN - 1);
6305         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6306
6307         /*
6308         // Translate the PEFileKind value to the value expected by the Windows loader
6309         */
6310         {
6311                 short kind;
6312
6313                 /*
6314                 // PEFileKinds.Dll == 1
6315                 // PEFileKinds.ConsoleApplication == 2
6316                 // PEFileKinds.WindowApplication == 3
6317                 //
6318                 // need to get:
6319                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6320                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6321                 */
6322                 if (assemblyb->pekind == 3)
6323                         kind = 2;
6324                 else
6325                         kind = 3;
6326                 
6327                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6328         }    
6329         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6330         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6331         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6332         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6333         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6334         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6335
6336         /* fill data directory entries */
6337
6338         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6339         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6340
6341         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6342         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6343
6344         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6345         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6346         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6347         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6348         /* patch entrypoint name */
6349         if (assemblyb->pekind == 1)
6350                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6351         else
6352                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6353         /* patch imported function RVA name */
6354         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6355         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6356
6357         /* the import table */
6358         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6359         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6360         /* patch imported dll RVA name and other entries in the dir */
6361         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6362         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6363         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6364         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6365         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6366         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6367
6368         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6369         value = (assembly->text_rva + assembly->imp_names_offset);
6370         *p++ = (value) & 0xff;
6371         *p++ = (value >> 8) & (0xff);
6372         *p++ = (value >> 16) & (0xff);
6373         *p++ = (value >> 24) & (0xff);
6374
6375         /* the CLI header info */
6376         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6377         cli_header->ch_size = GUINT32_FROM_LE (72);
6378         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6379         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6380         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6381         if (assemblyb->entry_point) {
6382                 guint32 table_idx = 0;
6383                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6384                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6385                         table_idx = methodb->table_idx;
6386                 } else {
6387                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6388                 }
6389                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6390         } else {
6391                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6392         }
6393         /* The embedded managed resources */
6394         text_offset = assembly->text_rva + assembly->code.index;
6395         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6396         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6397         text_offset += assembly->resources.index;
6398         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6399         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6400         text_offset += assembly->meta_size;
6401         if (assembly->strong_name_size) {
6402                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6403                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6404                 text_offset += assembly->strong_name_size;
6405         }
6406
6407         /* write the section tables and section content */
6408         section = (MonoSectionTable*)(pefile->data + section_start);
6409         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6410                 static const char section_names [][7] = {
6411                         ".text", ".rsrc", ".reloc"
6412                 };
6413                 if (!assembly->sections [i].size)
6414                         continue;
6415                 strcpy (section->st_name, section_names [i]);
6416                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6417                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6418                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6419                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6420                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6421                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6422                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6423                 section ++;
6424         }
6425         
6426         checked_write_file (file, pefile->data, pefile->index);
6427         
6428         mono_dynamic_stream_reset (pefile);
6429         
6430         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6431                 if (!assembly->sections [i].size)
6432                         continue;
6433                 
6434                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6435                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6436                 
6437                 switch (i) {
6438                 case MONO_SECTION_TEXT:
6439                         /* patch entry point */
6440                         p = (guchar*)(assembly->code.data + 2);
6441                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6442                         *p++ = (value) & 0xff;
6443                         *p++ = (value >> 8) & 0xff;
6444                         *p++ = (value >> 16) & 0xff;
6445                         *p++ = (value >> 24) & 0xff;
6446                 
6447                         checked_write_file (file, assembly->code.data, assembly->code.index);
6448                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6449                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6450                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6451                                 
6452
6453                         g_free (assembly->image.raw_metadata);
6454                         break;
6455                 case MONO_SECTION_RELOC: {
6456                         struct {
6457                                 guint32 page_rva;
6458                                 guint32 block_size;
6459                                 guint16 type_and_offset;
6460                                 guint16 term;
6461                         } reloc;
6462                         
6463                         g_assert (sizeof (reloc) == 12);
6464                         
6465                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6466                         reloc.block_size = GUINT32_FROM_LE (12);
6467                         
6468                         /* 
6469                          * the entrypoint is always at the start of the text section 
6470                          * 3 is IMAGE_REL_BASED_HIGHLOW
6471                          * 2 is patch_size_rva - text_rva
6472                          */
6473                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6474                         reloc.term = 0;
6475                         
6476                         checked_write_file (file, &reloc, sizeof (reloc));
6477                         
6478                         break;
6479                 }
6480                 case MONO_SECTION_RSRC:
6481                         if (assembly->win32_res) {
6482
6483                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6484                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6485                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6486                         }
6487                         break;
6488                 default:
6489                         g_assert_not_reached ();
6490                 }
6491         }
6492         
6493         /* check that the file is properly padded */
6494         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6495                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6496         if (! SetEndOfFile (file))
6497                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6498         
6499         mono_dynamic_stream_reset (&assembly->code);
6500         mono_dynamic_stream_reset (&assembly->us);
6501         mono_dynamic_stream_reset (&assembly->blob);
6502         mono_dynamic_stream_reset (&assembly->guid);
6503         mono_dynamic_stream_reset (&assembly->sheap);
6504
6505         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6506         g_hash_table_destroy (assembly->blob_cache);
6507         assembly->blob_cache = NULL;
6508
6509         return TRUE;
6510 }
6511
6512 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6513
6514 gboolean
6515 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6516 {
6517         g_assert_not_reached ();
6518 }
6519
6520 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6521
6522 #ifndef DISABLE_REFLECTION_EMIT
6523
6524 MonoReflectionModule *
6525 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6526 {
6527         MonoError error;
6528         MonoReflectionModule *result = NULL;
6529         char *name;
6530         MonoImage *image;
6531         MonoImageOpenStatus status;
6532         MonoDynamicAssembly *assembly;
6533         guint32 module_count;
6534         MonoImage **new_modules;
6535         gboolean *new_modules_loaded;
6536         
6537         name = mono_string_to_utf8 (fileName);
6538
6539         image = mono_image_open (name, &status);
6540         if (!image) {
6541                 MonoException *exc;
6542                 if (status == MONO_IMAGE_ERROR_ERRNO)
6543                         exc = mono_get_exception_file_not_found (fileName);
6544                 else
6545                         exc = mono_get_exception_bad_image_format (name);
6546                 g_free (name);
6547                 mono_raise_exception (exc);
6548         }
6549
6550         g_free (name);
6551
6552         assembly = ab->dynamic_assembly;
6553         image->assembly = (MonoAssembly*)assembly;
6554
6555         module_count = image->assembly->image->module_count;
6556         new_modules = g_new0 (MonoImage *, module_count + 1);
6557         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6558
6559         if (image->assembly->image->modules)
6560                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6561         if (image->assembly->image->modules_loaded)
6562                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6563         new_modules [module_count] = image;
6564         new_modules_loaded [module_count] = TRUE;
6565         mono_image_addref (image);
6566
6567         g_free (image->assembly->image->modules);
6568         image->assembly->image->modules = new_modules;
6569         image->assembly->image->modules_loaded = new_modules_loaded;
6570         image->assembly->image->module_count ++;
6571
6572         mono_assembly_load_references (image, &status);
6573         if (status) {
6574                 mono_image_close (image);
6575                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6576         }
6577
6578         result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6579         mono_error_raise_exception (&error); /* FIXME don't raise here */
6580         return result;
6581 }
6582
6583 #endif /* DISABLE_REFLECTION_EMIT */
6584
6585 /*
6586  * We need to return always the same object for MethodInfo, FieldInfo etc..
6587  * but we need to consider the reflected type.
6588  * type uses a different hash, since it uses custom hash/equal functions.
6589  */
6590
6591 typedef struct {
6592         gpointer item;
6593         MonoClass *refclass;
6594 } ReflectedEntry;
6595
6596 static gboolean
6597 reflected_equal (gconstpointer a, gconstpointer b) {
6598         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6599         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6600
6601         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6602 }
6603
6604 static guint
6605 reflected_hash (gconstpointer a) {
6606         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6607         return mono_aligned_addr_hash (ea->item);
6608 }
6609
6610 #define CHECK_OBJECT(t,p,k)     \
6611         do {    \
6612                 t _obj; \
6613                 ReflectedEntry e;       \
6614                 e.item = (p);   \
6615                 e.refclass = (k);       \
6616                 mono_domain_lock (domain);      \
6617                 if (!domain->refobject_hash)    \
6618                         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");  \
6619                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6620                         mono_domain_unlock (domain);    \
6621                         return _obj;    \
6622                 }       \
6623         mono_domain_unlock (domain); \
6624         } while (0)
6625
6626 #ifdef HAVE_BOEHM_GC
6627 /* ReflectedEntry doesn't need to be GC tracked */
6628 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6629 #define FREE_REFENTRY(entry) g_free ((entry))
6630 #define REFENTRY_REQUIRES_CLEANUP
6631 #else
6632 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6633 /* FIXME: */
6634 #define FREE_REFENTRY(entry)
6635 #endif
6636
6637 #define CACHE_OBJECT(t,p,o,k)   \
6638         do {    \
6639                 t _obj; \
6640         ReflectedEntry pe; \
6641         pe.item = (p); \
6642         pe.refclass = (k); \
6643         mono_domain_lock (domain); \
6644                 if (!domain->refobject_hash)    \
6645                         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");  \
6646         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6647         if (!_obj) { \
6648                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6649                     e->item = (p);      \
6650                     e->refclass = (k);  \
6651                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6652             _obj = o; \
6653         } \
6654                 mono_domain_unlock (domain);    \
6655         return _obj; \
6656         } while (0)
6657
6658 static void
6659 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6660 {
6661         mono_domain_lock (domain);
6662         if (domain->refobject_hash) {
6663         ReflectedEntry pe;
6664                 gpointer orig_pe, orig_value;
6665
6666                 pe.item = o;
6667                 pe.refclass = klass;
6668                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6669                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6670                         FREE_REFENTRY (orig_pe);
6671                 }
6672         }
6673         mono_domain_unlock (domain);
6674 }
6675
6676 #ifdef REFENTRY_REQUIRES_CLEANUP
6677 static void
6678 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6679 {
6680         FREE_REFENTRY (key);
6681 }
6682 #endif
6683
6684 void
6685 mono_reflection_cleanup_domain (MonoDomain *domain)
6686 {
6687         if (domain->refobject_hash) {
6688 /*let's avoid scanning the whole hashtable if not needed*/
6689 #ifdef REFENTRY_REQUIRES_CLEANUP
6690                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6691 #endif
6692                 mono_g_hash_table_destroy (domain->refobject_hash);
6693                 domain->refobject_hash = NULL;
6694         }
6695 }
6696
6697 #ifndef DISABLE_REFLECTION_EMIT
6698 static gpointer
6699 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6700 {
6701         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6702 }
6703
6704 static gpointer
6705 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6706 {
6707         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6708 }
6709
6710 void
6711 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6712 {
6713         MonoDynamicImage *image = moduleb->dynamic_image;
6714         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6715         if (!image) {
6716                 MonoError error;
6717                 int module_count;
6718                 MonoImage **new_modules;
6719                 MonoImage *ass;
6720                 char *name, *fqname;
6721                 /*
6722                  * FIXME: we already created an image in mono_image_basic_init (), but
6723                  * we don't know which module it belongs to, since that is only 
6724                  * determined at assembly save time.
6725                  */
6726                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6727                 name = mono_string_to_utf8 (ab->name);
6728                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6729                 if (!mono_error_ok (&error)) {
6730                         g_free (name);
6731                         mono_error_raise_exception (&error);
6732                 }
6733                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6734
6735                 moduleb->module.image = &image->image;
6736                 moduleb->dynamic_image = image;
6737                 register_module (mono_object_domain (moduleb), moduleb, image);
6738
6739                 /* register the module with the assembly */
6740                 ass = ab->dynamic_assembly->assembly.image;
6741                 module_count = ass->module_count;
6742                 new_modules = g_new0 (MonoImage *, module_count + 1);
6743
6744                 if (ass->modules)
6745                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6746                 new_modules [module_count] = &image->image;
6747                 mono_image_addref (&image->image);
6748
6749                 g_free (ass->modules);
6750                 ass->modules = new_modules;
6751                 ass->module_count ++;
6752         }
6753 }
6754
6755 void
6756 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6757 {
6758         MonoDynamicImage *image = moduleb->dynamic_image;
6759
6760         g_assert (type->type);
6761         image->wrappers_type = mono_class_from_mono_type (type->type);
6762 }
6763
6764 #endif
6765
6766 /*
6767  * mono_assembly_get_object:
6768  * @domain: an app domain
6769  * @assembly: an assembly
6770  *
6771  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6772  */
6773 MonoReflectionAssembly*
6774 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6775 {
6776         MonoError error;
6777         MonoReflectionAssembly *result;
6778         result = mono_assembly_get_object_checked (domain, assembly, &error);
6779         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6780         return result;
6781 }
6782 /*
6783  * mono_assembly_get_object_checked:
6784  * @domain: an app domain
6785  * @assembly: an assembly
6786  *
6787  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6788  */
6789 MonoReflectionAssembly*
6790 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6791 {
6792         MonoReflectionAssembly *res;
6793         
6794         mono_error_init (error);
6795
6796         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6797         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6798         if (!res)
6799                 return NULL;
6800         res->assembly = assembly;
6801
6802         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6803 }
6804
6805
6806
6807 MonoReflectionModule*   
6808 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6809 {
6810         MonoError error;
6811         MonoReflectionModule *result;
6812         result = mono_module_get_object_checked (domain, image, &error);
6813         mono_error_raise_exception (&error);
6814         return result;
6815 }
6816
6817 MonoReflectionModule*
6818 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6819 {
6820         MonoReflectionModule *res;
6821         char* basename;
6822         
6823         mono_error_init (error);
6824         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6825         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6826         if (!res)
6827                 return NULL;
6828
6829         res->image = image;
6830         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6831         if (!assm_obj)
6832                 return NULL;
6833         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6834
6835         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6836         basename = g_path_get_basename (image->name);
6837         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6838         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6839         
6840         g_free (basename);
6841
6842         if (image->assembly->image == image) {
6843                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6844         } else {
6845                 int i;
6846                 res->token = 0;
6847                 if (image->assembly->image->modules) {
6848                         for (i = 0; i < image->assembly->image->module_count; i++) {
6849                                 if (image->assembly->image->modules [i] == image)
6850                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6851                         }
6852                         g_assert (res->token);
6853                 }
6854         }
6855
6856         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6857 }
6858
6859 MonoReflectionModule*
6860 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6861 {
6862         MonoError error;
6863         MonoReflectionModule *result;
6864         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6865         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6866         return result;
6867 }
6868
6869 MonoReflectionModule*
6870 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6871 {
6872         MonoReflectionModule *res;
6873         MonoTableInfo *table;
6874         guint32 cols [MONO_FILE_SIZE];
6875         const char *name;
6876         guint32 i, name_idx;
6877         const char *val;
6878         
6879         mono_error_init (error);
6880
6881         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6882         if (!res)
6883                 return NULL;
6884
6885         table = &image->tables [MONO_TABLE_FILE];
6886         g_assert (table_index < table->rows);
6887         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6888
6889         res->image = NULL;
6890         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6891         if (!assm_obj)
6892                 return NULL;
6893         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6894         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6895
6896         /* Check whenever the row has a corresponding row in the moduleref table */
6897         table = &image->tables [MONO_TABLE_MODULEREF];
6898         for (i = 0; i < table->rows; ++i) {
6899                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6900                 val = mono_metadata_string_heap (image, name_idx);
6901                 if (strcmp (val, name) == 0)
6902                         res->image = image->modules [i];
6903         }
6904
6905         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6906         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6907         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6908         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6909         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6910
6911         return res;
6912 }
6913
6914 static gboolean
6915 verify_safe_for_managed_space (MonoType *type)
6916 {
6917         switch (type->type) {
6918 #ifdef DEBUG_HARDER
6919         case MONO_TYPE_ARRAY:
6920                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6921         case MONO_TYPE_PTR:
6922                 return verify_safe_for_managed_space (type->data.type);
6923         case MONO_TYPE_SZARRAY:
6924                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6925         case MONO_TYPE_GENERICINST: {
6926                 MonoGenericInst *inst = type->data.generic_class->inst;
6927                 int i;
6928                 if (!inst->is_open)
6929                         break;
6930                 for (i = 0; i < inst->type_argc; ++i)
6931                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6932                                 return FALSE;
6933                 return TRUE;
6934         }
6935 #endif
6936         case MONO_TYPE_VAR:
6937         case MONO_TYPE_MVAR:
6938                 return TRUE;
6939         default:
6940                 return TRUE;
6941         }
6942 }
6943
6944 static MonoType*
6945 mono_type_normalize (MonoType *type)
6946 {
6947         int i;
6948         MonoGenericClass *gclass;
6949         MonoGenericInst *ginst;
6950         MonoClass *gtd;
6951         MonoGenericContainer *gcontainer;
6952         MonoType **argv = NULL;
6953         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6954
6955         if (type->type != MONO_TYPE_GENERICINST)
6956                 return type;
6957
6958         gclass = type->data.generic_class;
6959         ginst = gclass->context.class_inst;
6960         if (!ginst->is_open)
6961                 return type;
6962
6963         gtd = gclass->container_class;
6964         gcontainer = gtd->generic_container;
6965         argv = g_newa (MonoType*, ginst->type_argc);
6966
6967         for (i = 0; i < ginst->type_argc; ++i) {
6968                 MonoType *t = ginst->type_argv [i], *norm;
6969                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6970                         is_denorm_gtd = FALSE;
6971                 norm = mono_type_normalize (t);
6972                 argv [i] = norm;
6973                 if (norm != t)
6974                         requires_rebind = TRUE;
6975         }
6976
6977         if (is_denorm_gtd)
6978                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6979
6980         if (requires_rebind) {
6981                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6982                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6983         }
6984
6985         return type;
6986 }
6987 /*
6988  * mono_type_get_object:
6989  * @domain: an app domain
6990  * @type: a type
6991  *
6992  * Return an System.MonoType object representing the type @type.
6993  */
6994 MonoReflectionType*
6995 mono_type_get_object (MonoDomain *domain, MonoType *type)
6996 {
6997         MonoError error;
6998         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6999         mono_error_raise_exception (&error);
7000
7001         return ret;
7002 }
7003
7004 MonoReflectionType*
7005 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7006 {
7007         MonoType *norm_type;
7008         MonoReflectionType *res;
7009         MonoClass *klass;
7010
7011         mono_error_init (error);
7012
7013         klass = mono_class_from_mono_type (type);
7014
7015         /*we must avoid using @type as it might have come
7016          * from a mono_metadata_type_dup and the caller
7017          * expects that is can be freed.
7018          * Using the right type from 
7019          */
7020         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7021
7022         /* void is very common */
7023         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7024                 return (MonoReflectionType*)domain->typeof_void;
7025
7026         /*
7027          * If the vtable of the given class was already created, we can use
7028          * the MonoType from there and avoid all locking and hash table lookups.
7029          * 
7030          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7031          * that the resulting object is different.   
7032          */
7033         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7034                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7035                 if (vtable && vtable->type)
7036                         return (MonoReflectionType *)vtable->type;
7037         }
7038
7039         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7040         mono_domain_lock (domain);
7041         if (!domain->type_hash)
7042                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7043                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7044         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7045                 mono_domain_unlock (domain);
7046                 mono_loader_unlock ();
7047                 return res;
7048         }
7049
7050         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7051          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7052          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7053          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7054          * artifact of how generics are encoded and should be transparent to managed code so we
7055          * need to weed out this diference when retrieving managed System.Type objects.
7056          */
7057         norm_type = mono_type_normalize (type);
7058         if (norm_type != type) {
7059                 res = mono_type_get_object_checked (domain, norm_type, error);
7060                 if (!mono_error_ok (error))
7061                         return NULL;
7062                 mono_g_hash_table_insert (domain->type_hash, type, res);
7063                 mono_domain_unlock (domain);
7064                 mono_loader_unlock ();
7065                 return res;
7066         }
7067
7068         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7069         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7070                 g_assert (0);
7071
7072         if (!verify_safe_for_managed_space (type)) {
7073                 mono_domain_unlock (domain);
7074                 mono_loader_unlock ();
7075                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7076                 return NULL;
7077         }
7078
7079         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7080                 gboolean is_type_done = TRUE;
7081                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7082                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7083                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7084                 */
7085                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7086                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7087
7088                         if (gparam->owner && gparam->owner->is_method) {
7089                                 MonoMethod *method = gparam->owner->owner.method;
7090                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7091                                         is_type_done = FALSE;
7092                         } else if (gparam->owner && !gparam->owner->is_method) {
7093                                 MonoClass *klass = gparam->owner->owner.klass;
7094                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7095                                         is_type_done = FALSE;
7096                         }
7097                 } 
7098
7099                 /* g_assert_not_reached (); */
7100                 /* should this be considered an error condition? */
7101                 if (is_type_done && !type->byref) {
7102                         mono_domain_unlock (domain);
7103                         mono_loader_unlock ();
7104                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7105                 }
7106         }
7107         /* This is stored in vtables/JITted code so it has to be pinned */
7108         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7109         if (!mono_error_ok (error))
7110                 return NULL;
7111
7112         res->type = type;
7113         mono_g_hash_table_insert (domain->type_hash, type, res);
7114
7115         if (type->type == MONO_TYPE_VOID)
7116                 domain->typeof_void = (MonoObject*)res;
7117
7118         mono_domain_unlock (domain);
7119         mono_loader_unlock ();
7120         return res;
7121 }
7122
7123 /*
7124  * mono_method_get_object:
7125  * @domain: an app domain
7126  * @method: a method
7127  * @refclass: the reflected type (can be NULL)
7128  *
7129  * Return an System.Reflection.MonoMethod object representing the method @method.
7130  */
7131 MonoReflectionMethod*
7132 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7133 {
7134         MonoError error;
7135         MonoReflectionMethod *ret = NULL;
7136         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7137         mono_error_raise_exception (&error);
7138         return ret;
7139 }
7140
7141 /*
7142  * mono_method_get_object_checked:
7143  * @domain: an app domain
7144  * @method: a method
7145  * @refclass: the reflected type (can be NULL)
7146  * @error: set on error.
7147  *
7148  * Return an System.Reflection.MonoMethod object representing the method @method.
7149  * Returns NULL and sets @error on error.
7150  */
7151 MonoReflectionMethod*
7152 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7153 {
7154         /*
7155          * We use the same C representation for methods and constructors, but the type 
7156          * name in C# is different.
7157          */
7158         MonoReflectionType *rt;
7159         MonoClass *klass;
7160         MonoReflectionMethod *ret;
7161
7162         mono_error_init (error);
7163
7164         if (method->is_inflated) {
7165                 MonoReflectionGenericMethod *gret;
7166
7167                 if (!refclass)
7168                         refclass = method->klass;
7169                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7170                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7171                         klass = mono_class_get_mono_generic_cmethod_class ();
7172                 } else {
7173                         klass = mono_class_get_mono_generic_method_class ();
7174                 }
7175                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7176                 if (!mono_error_ok (error))
7177                         goto leave;
7178                 gret->method.method = method;
7179
7180                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7181
7182                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7183                 if (!mono_error_ok (error))
7184                     goto leave;
7185
7186                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7187
7188                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7189         }
7190
7191         if (!refclass)
7192                 refclass = method->klass;
7193
7194         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7195         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7196                 klass = mono_class_get_mono_cmethod_class ();
7197         }
7198         else {
7199                 klass = mono_class_get_mono_method_class ();
7200         }
7201         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7202         if (!mono_error_ok (error))
7203                 goto leave;
7204         ret->method = method;
7205
7206         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7207         if (!mono_error_ok (error))
7208                 goto leave;
7209
7210         MONO_OBJECT_SETREF (ret, reftype, rt);
7211
7212         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7213
7214 leave:
7215         g_assert (!mono_error_ok (error));
7216         return NULL;
7217 }
7218
7219 /*
7220  * mono_method_clear_object:
7221  *
7222  *   Clear the cached reflection objects for the dynamic method METHOD.
7223  */
7224 void
7225 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7226 {
7227         MonoClass *klass;
7228         g_assert (method_is_dynamic (method));
7229
7230         klass = method->klass;
7231         while (klass) {
7232                 clear_cached_object (domain, method, klass);
7233                 klass = klass->parent;
7234         }
7235         /* Added by mono_param_get_objects () */
7236         clear_cached_object (domain, &(method->signature), NULL);
7237         klass = method->klass;
7238         while (klass) {
7239                 clear_cached_object (domain, &(method->signature), klass);
7240                 klass = klass->parent;
7241         }
7242 }
7243
7244 /*
7245  * mono_field_get_object:
7246  * @domain: an app domain
7247  * @klass: a type
7248  * @field: a field
7249  *
7250  * Return an System.Reflection.MonoField object representing the field @field
7251  * in class @klass.
7252  */
7253 MonoReflectionField*
7254 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7255 {
7256         MonoError error;
7257         MonoReflectionField *result;
7258         result = mono_field_get_object_checked (domain, klass, field, &error);
7259         mono_error_raise_exception (&error);
7260         return result;
7261 }
7262
7263 /*
7264  * mono_field_get_object_checked:
7265  * @domain: an app domain
7266  * @klass: a type
7267  * @field: a field
7268  * @error: set on error
7269  *
7270  * Return an System.Reflection.MonoField object representing the field @field
7271  * in class @klass. On error, returns NULL and sets @error.
7272  */
7273 MonoReflectionField*
7274 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7275 {
7276         MonoReflectionType *rt;
7277         MonoReflectionField *res;
7278
7279         mono_error_init (error);
7280
7281         CHECK_OBJECT (MonoReflectionField *, field, klass);
7282         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7283         if (!res)
7284                 return NULL;
7285         res->klass = klass;
7286         res->field = field;
7287         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7288
7289         if (is_field_on_inst (field)) {
7290                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7291
7292                 rt = mono_type_get_object_checked (domain, field->type, error);
7293                 if (!mono_error_ok (error))
7294                         return NULL;
7295
7296                 MONO_OBJECT_SETREF (res, type, rt);
7297         } else {
7298                 if (field->type) {
7299                         rt = mono_type_get_object_checked (domain, field->type, error);
7300                         if (!mono_error_ok (error))
7301                                 return NULL;
7302
7303                         MONO_OBJECT_SETREF (res, type, rt);
7304                 }
7305                 res->attrs = mono_field_get_flags (field);
7306         }
7307         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7308 }
7309
7310 /*
7311  * mono_property_get_object:
7312  * @domain: an app domain
7313  * @klass: a type
7314  * @property: a property
7315  *
7316  * Return an System.Reflection.MonoProperty object representing the property @property
7317  * in class @klass.
7318  */
7319 MonoReflectionProperty*
7320 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7321 {
7322         MonoError error;
7323         MonoReflectionProperty *result;
7324         result = mono_property_get_object_checked (domain, klass, property, &error);
7325         mono_error_raise_exception (&error);
7326         return result;
7327 }
7328
7329 /**
7330  * mono_property_get_object:
7331  * @domain: an app domain
7332  * @klass: a type
7333  * @property: a property
7334  * @error: set on error
7335  *
7336  * Return an System.Reflection.MonoProperty object representing the property @property
7337  * in class @klass.  On error returns NULL and sets @error.
7338  */
7339 MonoReflectionProperty*
7340 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7341 {
7342         MonoReflectionProperty *res;
7343
7344         mono_error_init (error);
7345
7346         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7347         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7348         if (!res)
7349                 return NULL;
7350         res->klass = klass;
7351         res->property = property;
7352         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7353 }
7354
7355 /*
7356  * mono_event_get_object:
7357  * @domain: an app domain
7358  * @klass: a type
7359  * @event: a event
7360  *
7361  * Return an System.Reflection.MonoEvent object representing the event @event
7362  * in class @klass.
7363  */
7364 MonoReflectionEvent*
7365 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7366 {
7367         MonoError error;
7368         MonoReflectionEvent *result;
7369         result = mono_event_get_object_checked (domain, klass, event, &error);
7370         mono_error_raise_exception (&error);
7371         return result;
7372 }
7373
7374 /**
7375  * mono_event_get_object_checked:
7376  * @domain: an app domain
7377  * @klass: a type
7378  * @event: a event
7379  * @error: set on error
7380  *
7381  * Return an System.Reflection.MonoEvent object representing the event @event
7382  * in class @klass. On failure sets @error and returns NULL
7383  */
7384 MonoReflectionEvent*
7385 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7386 {
7387         MonoReflectionEvent *res;
7388         MonoReflectionMonoEvent *mono_event;
7389
7390         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7391         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7392         if (!mono_event)
7393                 return NULL;
7394         mono_event->klass = klass;
7395         mono_event->event = event;
7396         res = (MonoReflectionEvent*)mono_event;
7397         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7398 }
7399
7400 /**
7401  * mono_get_reflection_missing_object:
7402  * @domain: Domain where the object lives
7403  *
7404  * Returns the System.Reflection.Missing.Value singleton object
7405  * (of type System.Reflection.Missing).
7406  *
7407  * Used as the value for ParameterInfo.DefaultValue when Optional
7408  * is present
7409  */
7410 static MonoObject *
7411 mono_get_reflection_missing_object (MonoDomain *domain)
7412 {
7413         MonoObject *obj;
7414         static MonoClassField *missing_value_field = NULL;
7415         
7416         if (!missing_value_field) {
7417                 MonoClass *missing_klass;
7418                 missing_klass = mono_class_get_missing_class ();
7419                 mono_class_init (missing_klass);
7420                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7421                 g_assert (missing_value_field);
7422         }
7423         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7424         g_assert (obj);
7425         return obj;
7426 }
7427
7428 static MonoObject*
7429 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7430 {
7431         if (!*dbnull)
7432                 *dbnull = mono_get_dbnull_object (domain);
7433         return *dbnull;
7434 }
7435
7436 static MonoObject*
7437 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7438 {
7439         if (!*reflection_missing)
7440                 *reflection_missing = mono_get_reflection_missing_object (domain);
7441         return *reflection_missing;
7442 }
7443
7444 /*
7445  * mono_param_get_objects:
7446  * @domain: an app domain
7447  * @method: a method
7448  *
7449  * Return an System.Reflection.ParameterInfo array object representing the parameters
7450  * in the method @method.
7451  */
7452 MonoArray*
7453 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7454 {
7455         static MonoClass *System_Reflection_ParameterInfo;
7456         static MonoClass *System_Reflection_ParameterInfo_array;
7457         MonoArray *res = NULL;
7458         MonoReflectionMethod *member = NULL;
7459         MonoReflectionParameter *param = NULL;
7460         char **names = NULL, **blobs = NULL;
7461         guint32 *types = NULL;
7462         MonoType *type = NULL;
7463         MonoObject *dbnull = NULL;
7464         MonoObject *missing = NULL;
7465         MonoMarshalSpec **mspecs = NULL;
7466         MonoMethodSignature *sig = NULL;
7467         MonoVTable *pinfo_vtable;
7468         MonoReflectionType *rt;
7469         int i;
7470
7471         mono_error_init (error);
7472         
7473         if (!System_Reflection_ParameterInfo_array) {
7474                 MonoClass *klass;
7475
7476                 klass = mono_class_get_mono_parameter_info_class ();
7477
7478                 mono_memory_barrier ();
7479                 System_Reflection_ParameterInfo = klass; 
7480
7481         
7482                 klass = mono_array_class_get (klass, 1);
7483                 mono_memory_barrier ();
7484                 System_Reflection_ParameterInfo_array = klass;
7485         }
7486
7487         sig = mono_method_signature_checked (method, error);
7488         if (!mono_error_ok (error))
7489                 goto leave;
7490
7491         if (!sig->param_count) {
7492                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7493                 if (!res)
7494                         goto leave;
7495
7496                 return res;
7497         }
7498
7499         /* Note: the cache is based on the address of the signature into the method
7500          * since we already cache MethodInfos with the method as keys.
7501          */
7502         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7503
7504         member = mono_method_get_object_checked (domain, method, refclass, error);
7505         if (!member)
7506                 goto leave;
7507         names = g_new (char *, sig->param_count);
7508         mono_method_get_param_names (method, (const char **) names);
7509
7510         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7511         mono_method_get_marshal_info (method, mspecs);
7512
7513         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7514         if (!res)
7515                 goto leave;
7516
7517         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7518         for (i = 0; i < sig->param_count; ++i) {
7519                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7520                 if (!param)
7521                         goto leave;
7522
7523                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7524                 if (!rt)
7525                         goto leave;
7526
7527                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7528
7529                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7530
7531                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7532
7533                 param->PositionImpl = i;
7534                 param->AttrsImpl = sig->params [i]->attrs;
7535
7536                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7537                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7538                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7539                         else
7540                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7541                 } else {
7542
7543                         if (!blobs) {
7544                                 blobs = g_new0 (char *, sig->param_count);
7545                                 types = g_new0 (guint32, sig->param_count);
7546                                 get_default_param_value_blobs (method, blobs, types); 
7547                         }
7548
7549                         /* Build MonoType for the type from the Constant Table */
7550                         if (!type)
7551                                 type = g_new0 (MonoType, 1);
7552                         type->type = (MonoTypeEnum)types [i];
7553                         type->data.klass = NULL;
7554                         if (types [i] == MONO_TYPE_CLASS)
7555                                 type->data.klass = mono_defaults.object_class;
7556                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7557                                 /* For enums, types [i] contains the base type */
7558
7559                                         type->type = MONO_TYPE_VALUETYPE;
7560                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7561                         } else
7562                                 type->data.klass = mono_class_from_mono_type (type);
7563
7564                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7565                         if (!is_ok (error))
7566                                 goto leave;
7567                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7568
7569                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7570                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7571                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7572                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7573                                 else
7574                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7575                         }
7576                         
7577                 }
7578
7579                 if (mspecs [i + 1]) {
7580                         MonoReflectionMarshalAsAttribute* mobj;
7581                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7582                         if (!mobj)
7583                                 goto leave;
7584                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7585                 }
7586                 
7587                 mono_array_setref (res, i, param);
7588         }
7589
7590 leave:
7591         g_free (names);
7592         g_free (blobs);
7593         g_free (types);
7594         g_free (type);
7595
7596         if (sig) {
7597                 for (i = sig->param_count; i >= 0; i--) {
7598                         if (mspecs [i])
7599                                 mono_metadata_free_marshal_spec (mspecs [i]);
7600                 }
7601         }
7602         g_free (mspecs);
7603
7604         if (!is_ok (error))
7605                 return NULL;
7606         
7607         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7608 }
7609
7610 MonoArray*
7611 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7612 {
7613         MonoError error;
7614         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7615         mono_error_assert_ok (&error);
7616         return result;
7617 }
7618
7619 /*
7620  * mono_method_body_get_object:
7621  * @domain: an app domain
7622  * @method: a method
7623  *
7624  * Return an System.Reflection.MethodBody object representing the method @method.
7625  */
7626 MonoReflectionMethodBody*
7627 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7628 {
7629         MonoError error;
7630         MonoReflectionMethodBody *ret;
7631         MonoMethodHeader *header;
7632         MonoImage *image;
7633         MonoReflectionType *rt;
7634         guint32 method_rva, local_var_sig_token;
7635     char *ptr;
7636         unsigned char format, flags;
7637         int i;
7638
7639         /* for compatibility with .net */
7640     if (method_is_dynamic (method))
7641         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7642
7643         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7644
7645         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7646                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7647             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7648                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7649             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7650                 return NULL;
7651
7652         image = method->klass->image;
7653         header = mono_method_get_header_checked (method, &error);
7654         mono_error_raise_exception (&error); /* FIXME don't raise here */
7655
7656         if (!image_is_dynamic (image)) {
7657                 /* Obtain local vars signature token */
7658                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7659                 ptr = mono_image_rva_map (image, method_rva);
7660                 flags = *(const unsigned char *) ptr;
7661                 format = flags & METHOD_HEADER_FORMAT_MASK;
7662                 switch (format){
7663                 case METHOD_HEADER_TINY_FORMAT:
7664                         local_var_sig_token = 0;
7665                         break;
7666                 case METHOD_HEADER_FAT_FORMAT:
7667                         ptr += 2;
7668                         ptr += 2;
7669                         ptr += 4;
7670                         local_var_sig_token = read32 (ptr);
7671                         break;
7672                 default:
7673                         g_assert_not_reached ();
7674                 }
7675         } else
7676                 local_var_sig_token = 0; //FIXME
7677
7678         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7679         mono_error_raise_exception (&error); /* FIXME don't raise here */
7680
7681         ret->init_locals = header->init_locals;
7682         ret->max_stack = header->max_stack;
7683         ret->local_var_sig_token = local_var_sig_token;
7684         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7685         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7686
7687         /* Locals */
7688         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7689         for (i = 0; i < header->num_locals; ++i) {
7690                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7691                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7692
7693                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7694                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7695
7696                 MONO_OBJECT_SETREF (info, local_type, rt);
7697
7698                 info->is_pinned = header->locals [i]->pinned;
7699                 info->local_index = i;
7700                 mono_array_setref (ret->locals, i, info);
7701         }
7702
7703         /* Exceptions */
7704         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7705         for (i = 0; i < header->num_clauses; ++i) {
7706                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7707                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7708                 MonoExceptionClause *clause = &header->clauses [i];
7709
7710                 info->flags = clause->flags;
7711                 info->try_offset = clause->try_offset;
7712                 info->try_length = clause->try_len;
7713                 info->handler_offset = clause->handler_offset;
7714                 info->handler_length = clause->handler_len;
7715                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7716                         info->filter_offset = clause->data.filter_offset;
7717                 else if (clause->data.catch_class) {
7718                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7719                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7720
7721                         MONO_OBJECT_SETREF (info, catch_type, rt);
7722                 }
7723
7724                 mono_array_setref (ret->clauses, i, info);
7725         }
7726
7727         mono_metadata_free_mh (header);
7728         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7729         return ret;
7730 }
7731
7732 /**
7733  * mono_get_dbnull_object:
7734  * @domain: Domain where the object lives
7735  *
7736  * Returns the System.DBNull.Value singleton object
7737  *
7738  * Used as the value for ParameterInfo.DefaultValue 
7739  */
7740 MonoObject *
7741 mono_get_dbnull_object (MonoDomain *domain)
7742 {
7743         MonoObject *obj;
7744         static MonoClassField *dbnull_value_field = NULL;
7745         
7746         if (!dbnull_value_field) {
7747                 MonoClass *dbnull_klass;
7748                 dbnull_klass = mono_class_get_dbnull_class ();
7749                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7750                 g_assert (dbnull_value_field);
7751         }
7752         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7753         g_assert (obj);
7754         return obj;
7755 }
7756
7757 static void
7758 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7759 {
7760         guint32 param_index, i, lastp, crow = 0;
7761         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7762         gint32 idx;
7763
7764         MonoClass *klass = method->klass;
7765         MonoImage *image = klass->image;
7766         MonoMethodSignature *methodsig = mono_method_signature (method);
7767
7768         MonoTableInfo *constt;
7769         MonoTableInfo *methodt;
7770         MonoTableInfo *paramt;
7771
7772         if (!methodsig->param_count)
7773                 return;
7774
7775         mono_class_init (klass);
7776
7777         if (image_is_dynamic (klass->image)) {
7778                 MonoReflectionMethodAux *aux;
7779                 if (method->is_inflated)
7780                         method = ((MonoMethodInflated*)method)->declaring;
7781                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7782                 if (aux && aux->param_defaults) {
7783                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7784                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7785                 }
7786                 return;
7787         }
7788
7789         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7790         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7791         constt = &image->tables [MONO_TABLE_CONSTANT];
7792
7793         idx = mono_method_get_index (method) - 1;
7794         g_assert (idx != -1);
7795
7796         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7797         if (idx + 1 < methodt->rows)
7798                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7799         else
7800                 lastp = paramt->rows + 1;
7801
7802         for (i = param_index; i < lastp; ++i) {
7803                 guint32 paramseq;
7804
7805                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7806                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7807
7808                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7809                         continue;
7810
7811                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7812                 if (!crow) {
7813                         continue;
7814                 }
7815         
7816                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7817                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7818                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7819         }
7820
7821         return;
7822 }
7823
7824 MonoObject *
7825 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
7826 {
7827         void *retval;
7828         MonoClass *klass;
7829         MonoObject *object;
7830         MonoType *basetype = type;
7831
7832         mono_error_init (error);
7833
7834         if (!blob)
7835                 return NULL;
7836         
7837         klass = mono_class_from_mono_type (type);
7838         if (klass->valuetype) {
7839                 object = mono_object_new_checked (domain, klass, error);
7840                 return_val_if_nok (error, NULL);
7841                 retval = ((gchar *) object + sizeof (MonoObject));
7842                 if (klass->enumtype)
7843                         basetype = mono_class_enum_basetype (klass);
7844         } else {
7845                 retval = &object;
7846         }
7847                         
7848         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7849                 return object;
7850         else
7851                 return NULL;
7852 }
7853
7854 static int
7855 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7856         int found_sep;
7857         char *s;
7858         gboolean quoted = FALSE;
7859
7860         memset (assembly, 0, sizeof (MonoAssemblyName));
7861         assembly->culture = "";
7862         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7863
7864         if (*p == '"') {
7865                 quoted = TRUE;
7866                 p++;
7867         }
7868         assembly->name = p;
7869         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7870                 p++;
7871         if (quoted) {
7872                 if (*p != '"')
7873                         return 1;
7874                 *p = 0;
7875                 p++;
7876         }
7877         if (*p != ',')
7878                 return 1;
7879         *p = 0;
7880         /* Remove trailing whitespace */
7881         s = p - 1;
7882         while (*s && g_ascii_isspace (*s))
7883                 *s-- = 0;
7884         p ++;
7885         while (g_ascii_isspace (*p))
7886                 p++;
7887         while (*p) {
7888                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7889                         p += 8;
7890                         assembly->major = strtoul (p, &s, 10);
7891                         if (s == p || *s != '.')
7892                                 return 1;
7893                         p = ++s;
7894                         assembly->minor = strtoul (p, &s, 10);
7895                         if (s == p || *s != '.')
7896                                 return 1;
7897                         p = ++s;
7898                         assembly->build = strtoul (p, &s, 10);
7899                         if (s == p || *s != '.')
7900                                 return 1;
7901                         p = ++s;
7902                         assembly->revision = strtoul (p, &s, 10);
7903                         if (s == p)
7904                                 return 1;
7905                         p = s;
7906                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7907                         p += 8;
7908                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7909                                 assembly->culture = "";
7910                                 p += 7;
7911                         } else {
7912                                 assembly->culture = p;
7913                                 while (*p && *p != ',') {
7914                                         p++;
7915                                 }
7916                         }
7917                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7918                         p += 15;
7919                         if (strncmp (p, "null", 4) == 0) {
7920                                 p += 4;
7921                         } else {
7922                                 int len;
7923                                 gchar *start = p;
7924                                 while (*p && *p != ',') {
7925                                         p++;
7926                                 }
7927                                 len = (p - start + 1);
7928                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7929                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7930                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7931                         }
7932                 } else {
7933                         while (*p && *p != ',')
7934                                 p++;
7935                 }
7936                 found_sep = 0;
7937                 while (g_ascii_isspace (*p) || *p == ',') {
7938                         *p++ = 0;
7939                         found_sep = 1;
7940                         continue;
7941                 }
7942                 /* failed */
7943                 if (!found_sep)
7944                         return 1;
7945         }
7946
7947         return 0;
7948 }
7949
7950 /*
7951  * mono_reflection_parse_type:
7952  * @name: type name
7953  *
7954  * Parse a type name as accepted by the GetType () method and output the info
7955  * extracted in the info structure.
7956  * the name param will be mangled, so, make a copy before passing it to this function.
7957  * The fields in info will be valid until the memory pointed to by name is valid.
7958  *
7959  * See also mono_type_get_name () below.
7960  *
7961  * Returns: 0 on parse error.
7962  */
7963 static int
7964 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7965                              MonoTypeNameParse *info)
7966 {
7967         char *start, *p, *w, *last_point, *startn;
7968         int in_modifiers = 0;
7969         int isbyref = 0, rank = 0, isptr = 0;
7970
7971         start = p = w = name;
7972
7973         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7974         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7975         info->name = info->name_space = NULL;
7976         info->nested = NULL;
7977         info->modifiers = NULL;
7978         info->type_arguments = NULL;
7979
7980         /* last_point separates the namespace from the name */
7981         last_point = NULL;
7982         /* Skips spaces */
7983         while (*p == ' ') p++, start++, w++, name++;
7984
7985         while (*p) {
7986                 switch (*p) {
7987                 case '+':
7988                         *p = 0; /* NULL terminate the name */
7989                         startn = p + 1;
7990                         info->nested = g_list_append (info->nested, startn);
7991                         /* we have parsed the nesting namespace + name */
7992                         if (info->name)
7993                                 break;
7994                         if (last_point) {
7995                                 info->name_space = start;
7996                                 *last_point = 0;
7997                                 info->name = last_point + 1;
7998                         } else {
7999                                 info->name_space = (char *)"";
8000                                 info->name = start;
8001                         }
8002                         break;
8003                 case '.':
8004                         last_point = p;
8005                         break;
8006                 case '\\':
8007                         ++p;
8008                         break;
8009                 case '&':
8010                 case '*':
8011                 case '[':
8012                 case ',':
8013                 case ']':
8014                         in_modifiers = 1;
8015                         break;
8016                 default:
8017                         break;
8018                 }
8019                 if (in_modifiers)
8020                         break;
8021                 // *w++ = *p++;
8022                 p++;
8023         }
8024         
8025         if (!info->name) {
8026                 if (last_point) {
8027                         info->name_space = start;
8028                         *last_point = 0;
8029                         info->name = last_point + 1;
8030                 } else {
8031                         info->name_space = (char *)"";
8032                         info->name = start;
8033                 }
8034         }
8035         while (*p) {
8036                 switch (*p) {
8037                 case '&':
8038                         if (isbyref) /* only one level allowed by the spec */
8039                                 return 0;
8040                         isbyref = 1;
8041                         isptr = 0;
8042                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8043                         *p++ = 0;
8044                         break;
8045                 case '*':
8046                         if (isbyref) /* pointer to ref not okay */
8047                                 return 0;
8048                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8049                         isptr = 1;
8050                         *p++ = 0;
8051                         break;
8052                 case '[':
8053                         if (isbyref) /* array of ref and generic ref are not okay */
8054                                 return 0;
8055                         //Decide if it's an array of a generic argument list
8056                         *p++ = 0;
8057
8058                         if (!*p) //XXX test
8059                                 return 0;
8060                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8061                                 isptr = 0;
8062                                 rank = 1;
8063                                 while (*p) {
8064                                         if (*p == ']')
8065                                                 break;
8066                                         if (*p == ',')
8067                                                 rank++;
8068                                         else if (*p == '*') /* '*' means unknown lower bound */
8069                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8070                                         else
8071                                                 return 0;
8072                                         ++p;
8073                                 }
8074                                 if (*p++ != ']')
8075                                         return 0;
8076                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8077                         } else {
8078                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8079                                         return 0;
8080                                 isptr = 0;
8081                                 info->type_arguments = g_ptr_array_new ();
8082                                 while (*p) {
8083                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8084                                         gboolean fqname = FALSE;
8085
8086                                         g_ptr_array_add (info->type_arguments, subinfo);
8087
8088                                         while (*p == ' ') p++;
8089                                         if (*p == '[') {
8090                                                 p++;
8091                                                 fqname = TRUE;
8092                                         }
8093
8094                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8095                                                 return 0;
8096
8097                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8098                                         if (fqname && (*p != ']')) {
8099                                                 char *aname;
8100
8101                                                 if (*p != ',')
8102                                                         return 0;
8103                                                 *p++ = 0;
8104
8105                                                 aname = p;
8106                                                 while (*p && (*p != ']'))
8107                                                         p++;
8108
8109                                                 if (*p != ']')
8110                                                         return 0;
8111
8112                                                 *p++ = 0;
8113                                                 while (*aname) {
8114                                                         if (g_ascii_isspace (*aname)) {
8115                                                                 ++aname;
8116                                                                 continue;
8117                                                         }
8118                                                         break;
8119                                                 }
8120                                                 if (!*aname ||
8121                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8122                                                         return 0;
8123                                         } else if (fqname && (*p == ']')) {
8124                                                 *p++ = 0;
8125                                         }
8126                                         if (*p == ']') {
8127                                                 *p++ = 0;
8128                                                 break;
8129                                         } else if (!*p) {
8130                                                 return 0;
8131                                         }
8132                                         *p++ = 0;
8133                                 }
8134                         }
8135                         break;
8136                 case ']':
8137                         if (is_recursed)
8138                                 goto end;
8139                         return 0;
8140                 case ',':
8141                         if (is_recursed)
8142                                 goto end;
8143                         *p++ = 0;
8144                         while (*p) {
8145                                 if (g_ascii_isspace (*p)) {
8146                                         ++p;
8147                                         continue;
8148                                 }
8149                                 break;
8150                         }
8151                         if (!*p)
8152                                 return 0; /* missing assembly name */
8153                         if (!assembly_name_to_aname (&info->assembly, p))
8154                                 return 0;
8155                         break;
8156                 default:
8157                         return 0;
8158                 }
8159                 if (info->assembly.name)
8160                         break;
8161         }
8162         // *w = 0; /* terminate class name */
8163  end:
8164         if (!info->name || !*info->name)
8165                 return 0;
8166         if (endptr)
8167                 *endptr = p;
8168         /* add other consistency checks */
8169         return 1;
8170 }
8171
8172
8173 /**
8174  * mono_identifier_unescape_type_name_chars:
8175  * @identifier: the display name of a mono type
8176  *
8177  * Returns:
8178  *  The name in internal form, that is without escaping backslashes.
8179  *
8180  *  The string is modified in place!
8181  */
8182 char*
8183 mono_identifier_unescape_type_name_chars(char* identifier)
8184 {
8185         char *w, *r;
8186         if (!identifier)
8187                 return NULL;
8188         for (w = r = identifier; *r != 0; r++)
8189         {
8190                 char c = *r;
8191                 if (c == '\\') {
8192                         r++;
8193                         if (*r == 0)
8194                                 break;
8195                         c = *r;
8196                 }
8197                 *w = c;
8198                 w++;
8199         }
8200         if (w != r)
8201                 *w = 0;
8202         return identifier;
8203 }
8204
8205 void
8206 mono_identifier_unescape_info (MonoTypeNameParse* info);
8207
8208 static void
8209 unescape_each_type_argument(void* data, void* user_data)
8210 {
8211         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8212         mono_identifier_unescape_info (info);
8213 }
8214
8215 static void
8216 unescape_each_nested_name (void* data, void* user_data)
8217 {
8218         char* nested_name = (char*) data;
8219         mono_identifier_unescape_type_name_chars(nested_name);
8220 }
8221
8222 /**
8223  * mono_identifier_unescape_info:
8224  *
8225  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8226  *
8227  * Returns: nothing.
8228  *
8229  * Destructively updates the info by unescaping the identifiers that
8230  * comprise the type namespace, name, nested types (if any) and
8231  * generic type arguments (if any).
8232  *
8233  * The resulting info has the names in internal form.
8234  *
8235  */
8236 void
8237 mono_identifier_unescape_info (MonoTypeNameParse *info)
8238 {
8239         if (!info)
8240                 return;
8241         mono_identifier_unescape_type_name_chars(info->name_space);
8242         mono_identifier_unescape_type_name_chars(info->name);
8243         // but don't escape info->assembly
8244         if (info->type_arguments)
8245                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8246         if (info->nested)
8247                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8248 }
8249
8250 int
8251 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8252 {
8253         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8254         if (ok) {
8255                 mono_identifier_unescape_info (info);
8256         }
8257         return ok;
8258 }
8259
8260 static MonoType*
8261 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8262 {
8263         gboolean type_resolve = FALSE;
8264         MonoType *type;
8265         MonoImage *rootimage = image;
8266
8267         mono_error_init (error);
8268
8269         if (info->assembly.name) {
8270                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8271                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8272                         /* 
8273                          * This could happen in the AOT compiler case when the search hook is not
8274                          * installed.
8275                          */
8276                         assembly = image->assembly;
8277                 if (!assembly) {
8278                         /* then we must load the assembly ourselve - see #60439 */
8279                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8280                         if (!assembly)
8281                                 return NULL;
8282                 }
8283                 image = assembly->image;
8284         } else if (!image) {
8285                 image = mono_defaults.corlib;
8286         }
8287
8288         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8289         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8290                 mono_error_cleanup (error);
8291                 image = mono_defaults.corlib;
8292                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8293         }
8294
8295         return type;
8296 }
8297
8298 /**
8299  * mono_reflection_get_type_internal:
8300  *
8301  * Returns: may return NULL on success, sets error on failure.
8302  */
8303 static MonoType*
8304 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8305 {
8306         MonoClass *klass;
8307         GList *mod;
8308         int modval;
8309         gboolean bounded = FALSE;
8310         
8311         mono_error_init (error);
8312         if (!image)
8313                 image = mono_defaults.corlib;
8314
8315         if (!rootimage)
8316                 rootimage = mono_defaults.corlib;
8317
8318         if (ignorecase)
8319                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8320         else
8321                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8322
8323         if (!klass)
8324                 return NULL;
8325
8326         for (mod = info->nested; mod; mod = mod->next) {
8327                 gpointer iter = NULL;
8328                 MonoClass *parent;
8329
8330                 parent = klass;
8331                 mono_class_init (parent);
8332
8333                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8334                         char *lastp;
8335                         char *nested_name, *nested_nspace;
8336                         gboolean match = TRUE;
8337
8338                         lastp = strrchr ((const char *)mod->data, '.');
8339                         if (lastp) {
8340                                 /* Nested classes can have namespaces */
8341                                 int nspace_len;
8342
8343                                 nested_name = g_strdup (lastp + 1);
8344                                 nspace_len = lastp - (char*)mod->data;
8345                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8346                                 memcpy (nested_nspace, mod->data, nspace_len);
8347                                 nested_nspace [nspace_len] = '\0';
8348
8349                         } else {
8350                                 nested_name = (char *)mod->data;
8351                                 nested_nspace = NULL;
8352                         }
8353
8354                         if (nested_nspace) {
8355                                 if (ignorecase) {
8356                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8357                                                 match = FALSE;
8358                                 } else {
8359                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8360                                                 match = FALSE;
8361                                 }
8362                         }
8363                         if (match) {
8364                                 if (ignorecase) {
8365                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8366                                                 match = FALSE;
8367                                 } else {
8368                                         if (strcmp (klass->name, nested_name) != 0)
8369                                                 match = FALSE;
8370                                 }
8371                         }
8372                         if (lastp) {
8373                                 g_free (nested_name);
8374                                 g_free (nested_nspace);
8375                         }
8376                         if (match)
8377                                 break;
8378                 }
8379
8380                 if (!klass)
8381                         break;
8382         }
8383         if (!klass)
8384                 return NULL;
8385
8386         if (info->type_arguments) {
8387                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8388                 MonoReflectionType *the_type;
8389                 MonoType *instance;
8390                 int i;
8391
8392                 for (i = 0; i < info->type_arguments->len; i++) {
8393                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8394
8395                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8396                         if (!type_args [i]) {
8397                                 g_free (type_args);
8398                                 return NULL;
8399                         }
8400                 }
8401
8402                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8403                 if (!the_type)
8404                         return NULL;
8405
8406                 instance = mono_reflection_bind_generic_parameters (
8407                         the_type, info->type_arguments->len, type_args);
8408
8409                 g_free (type_args);
8410                 if (!instance)
8411                         return NULL;
8412
8413                 klass = mono_class_from_mono_type (instance);
8414         }
8415
8416         for (mod = info->modifiers; mod; mod = mod->next) {
8417                 modval = GPOINTER_TO_UINT (mod->data);
8418                 if (!modval) { /* byref: must be last modifier */
8419                         return &klass->this_arg;
8420                 } else if (modval == -1) {
8421                         klass = mono_ptr_class_get (&klass->byval_arg);
8422                 } else if (modval == -2) {
8423                         bounded = TRUE;
8424                 } else { /* array rank */
8425                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8426                 }
8427         }
8428
8429         return &klass->byval_arg;
8430 }
8431
8432 /*
8433  * mono_reflection_get_type:
8434  * @image: a metadata context
8435  * @info: type description structure
8436  * @ignorecase: flag for case-insensitive string compares
8437  * @type_resolve: whenever type resolve was already tried
8438  *
8439  * Build a MonoType from the type description in @info.
8440  * 
8441  */
8442
8443 MonoType*
8444 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8445         MonoError error;
8446         MonoType *result = mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve, &error);
8447         mono_error_raise_exception (&error); /* FIXME don't raise here */
8448         return result;
8449 }
8450
8451 static MonoType*
8452 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8453 {
8454         MonoReflectionAssemblyBuilder *abuilder;
8455         MonoType *type;
8456         int i;
8457
8458         mono_error_init (error);
8459         g_assert (assembly_is_dynamic (assembly));
8460         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8461         if (!abuilder)
8462                 return NULL;
8463
8464         /* Enumerate all modules */
8465
8466         type = NULL;
8467         if (abuilder->modules) {
8468                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8469                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8470                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8471                         if (type)
8472                                 break;
8473                         if (!mono_error_ok (error))
8474                                 return NULL;
8475                 }
8476         }
8477
8478         if (!type && abuilder->loaded_modules) {
8479                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8480                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8481                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8482                         if (type)
8483                                 break;
8484                         if (!mono_error_ok (error))
8485                                 return NULL;
8486                 }
8487         }
8488
8489         return type;
8490 }
8491         
8492 MonoType*
8493 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8494 {
8495         MonoType *type;
8496         MonoReflectionAssembly *assembly;
8497         GString *fullName;
8498         GList *mod;
8499
8500         mono_error_init (error);
8501
8502         if (image && image_is_dynamic (image))
8503                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8504         else {
8505                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8506         }
8507         return_val_if_nok (error, NULL);
8508
8509         if (type)
8510                 return type;
8511         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8512                 return NULL;
8513
8514         if (type_resolve) {
8515                 if (*type_resolve) 
8516                         return NULL;
8517                 else
8518                         *type_resolve = TRUE;
8519         }
8520         
8521         /* Reconstruct the type name */
8522         fullName = g_string_new ("");
8523         if (info->name_space && (info->name_space [0] != '\0'))
8524                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8525         else
8526                 g_string_printf (fullName, "%s", info->name);
8527         for (mod = info->nested; mod; mod = mod->next)
8528                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8529
8530         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8531         if (!is_ok (error)) {
8532                 g_string_free (fullName, TRUE);
8533                 return NULL;
8534         }
8535
8536         if (assembly) {
8537                 if (assembly_is_dynamic (assembly->assembly))
8538                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8539                                                                           info, ignorecase, error);
8540                 else
8541                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8542                                                                   info, ignorecase, error);
8543         }
8544         g_string_free (fullName, TRUE);
8545         return_val_if_nok (error, NULL);
8546         return type;
8547 }
8548
8549 void
8550 mono_reflection_free_type_info (MonoTypeNameParse *info)
8551 {
8552         g_list_free (info->modifiers);
8553         g_list_free (info->nested);
8554
8555         if (info->type_arguments) {
8556                 int i;
8557
8558                 for (i = 0; i < info->type_arguments->len; i++) {
8559                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8560
8561                         mono_reflection_free_type_info (subinfo);
8562                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8563                         g_free (subinfo);
8564                 }
8565
8566                 g_ptr_array_free (info->type_arguments, TRUE);
8567         }
8568 }
8569
8570 /*
8571  * mono_reflection_type_from_name:
8572  * @name: type name.
8573  * @image: a metadata context (can be NULL).
8574  *
8575  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8576  * it defaults to get the type from @image or, if @image is NULL or loading
8577  * from it fails, uses corlib.
8578  * 
8579  */
8580 MonoType*
8581 mono_reflection_type_from_name (char *name, MonoImage *image)
8582 {
8583         MonoError error;
8584         MonoType  *result = mono_reflection_type_from_name_checked (name, image, &error);
8585         mono_error_cleanup (&error);
8586         return result;
8587 }
8588
8589 /**
8590  * mono_reflection_type_from_name_checked:
8591  * @name: type name.
8592  * @image: a metadata context (can be NULL).
8593  * @error: set on errror.
8594  *
8595  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8596  * it defaults to get the type from @image or, if @image is NULL or loading
8597  * from it fails, uses corlib.  On failure returns NULL and sets @error.
8598  * 
8599  */
8600 MonoType*
8601 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8602 {
8603         MonoType *type = NULL;
8604         MonoTypeNameParse info;
8605         char *tmp;
8606
8607         mono_error_init (error);
8608         /* Make a copy since parse_type modifies its argument */
8609         tmp = g_strdup (name);
8610         
8611         /*g_print ("requested type %s\n", str);*/
8612         if (mono_reflection_parse_type (tmp, &info)) {
8613                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8614                 if (!is_ok (error)) {
8615                         g_free (tmp);
8616                         mono_reflection_free_type_info (&info);
8617                         return NULL;
8618                 }
8619         }
8620
8621         g_free (tmp);
8622         mono_reflection_free_type_info (&info);
8623         return type;
8624 }
8625
8626 /*
8627  * mono_reflection_get_token:
8628  *
8629  *   Return the metadata token of OBJ which should be an object
8630  * representing a metadata element.
8631  */
8632 guint32
8633 mono_reflection_get_token (MonoObject *obj)
8634 {
8635         MonoError error;
8636         MonoClass *klass;
8637         guint32 token = 0;
8638
8639         klass = obj->vtable->klass;
8640
8641         if (strcmp (klass->name, "MethodBuilder") == 0) {
8642                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8643
8644                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8645         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8646                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8647
8648                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8649         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8650                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8651
8652                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8653         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8654                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8655                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8656         } else if (strcmp (klass->name, "MonoType") == 0) {
8657                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8658                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8659                 MonoClass *mc = mono_class_from_mono_type (type);
8660                 if (!mono_class_init (mc))
8661                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8662
8663                 token = mc->type_token;
8664         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8665                    strcmp (klass->name, "MonoMethod") == 0 ||
8666                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8667                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8668                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8669                 if (m->method->is_inflated) {
8670                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8671                         return inflated->declaring->token;
8672                 } else {
8673                         token = m->method->token;
8674                 }
8675         } else if (strcmp (klass->name, "MonoField") == 0) {
8676                 MonoReflectionField *f = (MonoReflectionField*)obj;
8677
8678                 if (is_field_on_inst (f->field)) {
8679                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8680
8681                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8682                                 int field_index = f->field - dgclass->fields;
8683                                 MonoObject *obj;
8684
8685                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8686                                 obj = dgclass->field_objects [field_index];
8687                                 return mono_reflection_get_token (obj);
8688                         }
8689                 }
8690                 token = mono_class_get_field_token (f->field);
8691         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8692                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8693
8694                 token = mono_class_get_property_token (p->property);
8695         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8696                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8697
8698                 token = mono_class_get_event_token (p->event);
8699         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8700                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8701                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8702                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8703
8704                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8705         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8706                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8707
8708                 token = m->token;
8709         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8710                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8711         } else {
8712                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8713                 MonoException *ex = mono_get_exception_not_implemented (msg);
8714                 g_free (msg);
8715                 mono_raise_exception (ex);
8716         }
8717
8718         return token;
8719 }
8720
8721 static MonoClass*
8722 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8723 {
8724         char *n;
8725         MonoType *t;
8726         int slen = mono_metadata_decode_value (p, &p);
8727
8728         mono_error_init (error);
8729
8730         n = (char *)g_memdup (p, slen + 1);
8731         n [slen] = 0;
8732         t = mono_reflection_type_from_name_checked (n, image, error);
8733         if (!t) {
8734                 char *msg = g_strdup (mono_error_get_message (error));
8735                 mono_error_cleanup (error);
8736                 /* We don't free n, it's consumed by mono_error */
8737                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8738                 g_free (msg);
8739                 return NULL;
8740         }
8741         g_free (n);
8742         p += slen;
8743         *end = p;
8744         return mono_class_from_mono_type (t);
8745 }
8746
8747 static void*
8748 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8749 {
8750         int slen, type = t->type;
8751         MonoClass *tklass = t->data.klass;
8752
8753         mono_error_init (error);
8754
8755 handle_enum:
8756         switch (type) {
8757         case MONO_TYPE_U1:
8758         case MONO_TYPE_I1:
8759         case MONO_TYPE_BOOLEAN: {
8760                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8761                 *bval = *p;
8762                 *end = p + 1;
8763                 return bval;
8764         }
8765         case MONO_TYPE_CHAR:
8766         case MONO_TYPE_U2:
8767         case MONO_TYPE_I2: {
8768                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8769                 *val = read16 (p);
8770                 *end = p + 2;
8771                 return val;
8772         }
8773 #if SIZEOF_VOID_P == 4
8774         case MONO_TYPE_U:
8775         case MONO_TYPE_I:
8776 #endif
8777         case MONO_TYPE_R4:
8778         case MONO_TYPE_U4:
8779         case MONO_TYPE_I4: {
8780                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8781                 *val = read32 (p);
8782                 *end = p + 4;
8783                 return val;
8784         }
8785 #if SIZEOF_VOID_P == 8
8786         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8787         case MONO_TYPE_I:
8788 #endif
8789         case MONO_TYPE_U8:
8790         case MONO_TYPE_I8: {
8791                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8792                 *val = read64 (p);
8793                 *end = p + 8;
8794                 return val;
8795         }
8796         case MONO_TYPE_R8: {
8797                 double *val = (double *)g_malloc (sizeof (double));
8798                 readr8 (p, val);
8799                 *end = p + 8;
8800                 return val;
8801         }
8802         case MONO_TYPE_VALUETYPE:
8803                 if (t->data.klass->enumtype) {
8804                         type = mono_class_enum_basetype (t->data.klass)->type;
8805                         goto handle_enum;
8806                 } else {
8807                         MonoClass *k =  t->data.klass;
8808                         
8809                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8810                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8811                                 *val = read64 (p);
8812                                 *end = p + 8;
8813                                 return val;
8814                         }
8815                 }
8816                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8817                 break;
8818                 
8819         case MONO_TYPE_STRING:
8820                 if (*p == (char)0xFF) {
8821                         *end = p + 1;
8822                         return NULL;
8823                 }
8824                 slen = mono_metadata_decode_value (p, &p);
8825                 *end = p + slen;
8826                 return mono_string_new_len (mono_domain_get (), p, slen);
8827         case MONO_TYPE_CLASS: {
8828                 MonoReflectionType *rt;
8829                 char *n;
8830                 MonoType *t;
8831                 if (*p == (char)0xFF) {
8832                         *end = p + 1;
8833                         return NULL;
8834                 }
8835 handle_type:
8836                 slen = mono_metadata_decode_value (p, &p);
8837                 n = (char *)g_memdup (p, slen + 1);
8838                 n [slen] = 0;
8839                 t = mono_reflection_type_from_name_checked (n, image, error);
8840                 if (!t) {
8841                         char *msg = g_strdup (mono_error_get_message (error));
8842                         mono_error_cleanup (error);
8843                         /* We don't free n, it's consumed by mono_error */
8844                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
8845                         g_free (msg);
8846                         return NULL;
8847                 }
8848                 g_free (n);
8849                 *end = p + slen;
8850
8851                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8852                 if (!mono_error_ok (error))
8853                         return NULL;
8854
8855                 return rt;
8856         }
8857         case MONO_TYPE_OBJECT: {
8858                 char subt = *p++;
8859                 MonoObject *obj;
8860                 MonoClass *subc = NULL;
8861                 void *val;
8862
8863                 if (subt == 0x50) {
8864                         goto handle_type;
8865                 } else if (subt == 0x0E) {
8866                         type = MONO_TYPE_STRING;
8867                         goto handle_enum;
8868                 } else if (subt == 0x1D) {
8869                         MonoType simple_type = {{0}};
8870                         int etype = *p;
8871                         p ++;
8872
8873                         type = MONO_TYPE_SZARRAY;
8874                         if (etype == 0x50) {
8875                                 tklass = mono_defaults.systemtype_class;
8876                         } else if (etype == 0x55) {
8877                                 tklass = load_cattr_enum_type (image, p, &p, error);
8878                                 if (!mono_error_ok (error))
8879                                         return NULL;
8880                         } else {
8881                                 if (etype == 0x51)
8882                                         /* See Partition II, Appendix B3 */
8883                                         etype = MONO_TYPE_OBJECT;
8884                                 simple_type.type = (MonoTypeEnum)etype;
8885                                 tklass = mono_class_from_mono_type (&simple_type);
8886                         }
8887                         goto handle_enum;
8888                 } else if (subt == 0x55) {
8889                         char *n;
8890                         MonoType *t;
8891                         slen = mono_metadata_decode_value (p, &p);
8892                         n = (char *)g_memdup (p, slen + 1);
8893                         n [slen] = 0;
8894                         t = mono_reflection_type_from_name_checked (n, image, error);
8895                         if (!t) {
8896                                 char *msg = g_strdup (mono_error_get_message (error));
8897                                 mono_error_cleanup (error);
8898                                 /* We don't free n, it's consumed by mono_error */
8899                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
8900                                 g_free (msg);
8901                                 return NULL;
8902                         }
8903                         g_free (n);
8904                         p += slen;
8905                         subc = mono_class_from_mono_type (t);
8906                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8907                         MonoType simple_type = {{0}};
8908                         simple_type.type = (MonoTypeEnum)subt;
8909                         subc = mono_class_from_mono_type (&simple_type);
8910                 } else {
8911                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8912                 }
8913                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8914                 obj = NULL;
8915                 if (mono_error_ok (error)) {
8916                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
8917                         g_assert (!subc->has_references);
8918                         if (mono_error_ok (error))
8919                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8920                 }
8921
8922                 g_free (val);
8923                 return obj;
8924         }
8925         case MONO_TYPE_SZARRAY: {
8926                 MonoArray *arr;
8927                 guint32 i, alen, basetype;
8928                 alen = read32 (p);
8929                 p += 4;
8930                 if (alen == 0xffffffff) {
8931                         *end = p;
8932                         return NULL;
8933                 }
8934                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8935                 basetype = tklass->byval_arg.type;
8936                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8937                         basetype = mono_class_enum_basetype (tklass)->type;
8938                 switch (basetype)
8939                 {
8940                         case MONO_TYPE_U1:
8941                         case MONO_TYPE_I1:
8942                         case MONO_TYPE_BOOLEAN:
8943                                 for (i = 0; i < alen; i++) {
8944                                         MonoBoolean val = *p++;
8945                                         mono_array_set (arr, MonoBoolean, i, val);
8946                                 }
8947                                 break;
8948                         case MONO_TYPE_CHAR:
8949                         case MONO_TYPE_U2:
8950                         case MONO_TYPE_I2:
8951                                 for (i = 0; i < alen; i++) {
8952                                         guint16 val = read16 (p);
8953                                         mono_array_set (arr, guint16, i, val);
8954                                         p += 2;
8955                                 }
8956                                 break;
8957                         case MONO_TYPE_R4:
8958                         case MONO_TYPE_U4:
8959                         case MONO_TYPE_I4:
8960                                 for (i = 0; i < alen; i++) {
8961                                         guint32 val = read32 (p);
8962                                         mono_array_set (arr, guint32, i, val);
8963                                         p += 4;
8964                                 }
8965                                 break;
8966                         case MONO_TYPE_R8:
8967                                 for (i = 0; i < alen; i++) {
8968                                         double val;
8969                                         readr8 (p, &val);
8970                                         mono_array_set (arr, double, i, val);
8971                                         p += 8;
8972                                 }
8973                                 break;
8974                         case MONO_TYPE_U8:
8975                         case MONO_TYPE_I8:
8976                                 for (i = 0; i < alen; i++) {
8977                                         guint64 val = read64 (p);
8978                                         mono_array_set (arr, guint64, i, val);
8979                                         p += 8;
8980                                 }
8981                                 break;
8982                         case MONO_TYPE_CLASS:
8983                         case MONO_TYPE_OBJECT:
8984                         case MONO_TYPE_STRING:
8985                         case MONO_TYPE_SZARRAY:
8986                                 for (i = 0; i < alen; i++) {
8987                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8988                                         if (!mono_error_ok (error))
8989                                                 return NULL;
8990                                         mono_array_setref (arr, i, item);
8991                                 }
8992                                 break;
8993                         default:
8994                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8995                 }
8996                 *end=p;
8997                 return arr;
8998         }
8999         default:
9000                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9001         }
9002         return NULL;
9003 }
9004
9005 static MonoObject*
9006 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9007 {
9008         static MonoMethod *ctor;
9009         MonoObject *retval;
9010         void *params [2], *unboxed;
9011
9012         mono_error_init (error);
9013
9014         if (!ctor)
9015                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9016         
9017         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9018         return_val_if_nok (error, NULL);
9019
9020         params [1] = val;
9021         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9022         return_val_if_nok (error, NULL);
9023         unboxed = mono_object_unbox (retval);
9024
9025         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9026         return_val_if_nok (error, NULL);
9027
9028         return retval;
9029 }
9030
9031 static MonoObject*
9032 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9033 {
9034         static MonoMethod *ctor;
9035         MonoObject *retval;
9036         void *unboxed, *params [2];
9037
9038         mono_error_init (error);
9039
9040         if (!ctor)
9041                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9042
9043         params [0] = minfo;
9044         params [1] = typedarg;
9045         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9046         return_val_if_nok (error, NULL);
9047
9048         unboxed = mono_object_unbox (retval);
9049
9050         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9051         return_val_if_nok (error, NULL);
9052
9053         return retval;
9054 }
9055
9056 static gboolean
9057 type_is_reference (MonoType *type)
9058 {
9059         switch (type->type) {
9060         case MONO_TYPE_BOOLEAN:
9061         case MONO_TYPE_CHAR:
9062         case MONO_TYPE_U:
9063         case MONO_TYPE_I:
9064         case MONO_TYPE_U1:
9065         case MONO_TYPE_I1:
9066         case MONO_TYPE_U2:
9067         case MONO_TYPE_I2:
9068         case MONO_TYPE_U4:
9069         case MONO_TYPE_I4:
9070         case MONO_TYPE_U8:
9071         case MONO_TYPE_I8:
9072         case MONO_TYPE_R8:
9073         case MONO_TYPE_R4:
9074         case MONO_TYPE_VALUETYPE:
9075                 return FALSE;
9076         default:
9077                 return TRUE;
9078         }
9079 }
9080
9081 static void
9082 free_param_data (MonoMethodSignature *sig, void **params) {
9083         int i;
9084         for (i = 0; i < sig->param_count; ++i) {
9085                 if (!type_is_reference (sig->params [i]))
9086                         g_free (params [i]);
9087         }
9088 }
9089
9090 /*
9091  * Find the field index in the metadata FieldDef table.
9092  */
9093 static guint32
9094 find_field_index (MonoClass *klass, MonoClassField *field) {
9095         int i;
9096
9097         for (i = 0; i < klass->field.count; ++i) {
9098                 if (field == &klass->fields [i])
9099                         return klass->field.first + 1 + i;
9100         }
9101         return 0;
9102 }
9103
9104 /*
9105  * Find the property index in the metadata Property table.
9106  */
9107 static guint32
9108 find_property_index (MonoClass *klass, MonoProperty *property) {
9109         int i;
9110
9111         for (i = 0; i < klass->ext->property.count; ++i) {
9112                 if (property == &klass->ext->properties [i])
9113                         return klass->ext->property.first + 1 + i;
9114         }
9115         return 0;
9116 }
9117
9118 /*
9119  * Find the event index in the metadata Event table.
9120  */
9121 static guint32
9122 find_event_index (MonoClass *klass, MonoEvent *event) {
9123         int i;
9124
9125         for (i = 0; i < klass->ext->event.count; ++i) {
9126                 if (event == &klass->ext->events [i])
9127                         return klass->ext->event.first + 1 + i;
9128         }
9129         return 0;
9130 }
9131
9132 static MonoObject*
9133 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9134 {
9135         const char *p = (const char*)data;
9136         const char *named;
9137         guint32 i, j, num_named;
9138         MonoObject *attr;
9139         void *params_buf [32];
9140         void **params = NULL;
9141         MonoMethodSignature *sig;
9142         MonoObject *exc = NULL;
9143
9144         mono_error_init (error);
9145
9146         mono_class_init (method->klass);
9147
9148         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9149                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9150                 return NULL;
9151         }
9152
9153         if (len == 0) {
9154                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9155                 if (!mono_error_ok (error)) return NULL;
9156
9157                 mono_runtime_invoke_checked (method, attr, NULL, error);
9158                 if (!mono_error_ok (error))
9159                         return NULL;
9160
9161                 return attr;
9162         }
9163
9164         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9165                 return NULL;
9166
9167         /*g_print ("got attr %s\n", method->klass->name);*/
9168
9169         sig = mono_method_signature (method);
9170         if (sig->param_count < 32) {
9171                 params = params_buf;
9172                 memset (params, 0, sizeof (void*) * sig->param_count);
9173         } else {
9174                 /* Allocate using GC so it gets GC tracking */
9175                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9176         }
9177
9178         /* skip prolog */
9179         p += 2;
9180         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9181                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9182                 if (!mono_error_ok (error))
9183                         goto fail;
9184         }
9185
9186         named = p;
9187         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9188         if (!mono_error_ok (error)) goto fail;
9189
9190         mono_runtime_try_invoke (method, attr, params, &exc, error);
9191         if (!mono_error_ok (error))
9192                 goto fail;
9193         if (exc)
9194                 goto fail;
9195
9196         num_named = read16 (named);
9197         named += 2;
9198         for (j = 0; j < num_named; j++) {
9199                 gint name_len;
9200                 char *name, named_type, data_type;
9201                 named_type = *named++;
9202                 data_type = *named++; /* type of data */
9203                 if (data_type == MONO_TYPE_SZARRAY)
9204                         data_type = *named++;
9205                 if (data_type == MONO_TYPE_ENUM) {
9206                         gint type_len;
9207                         char *type_name;
9208                         type_len = mono_metadata_decode_blob_size (named, &named);
9209                         type_name = (char *)g_malloc (type_len + 1);
9210                         memcpy (type_name, named, type_len);
9211                         type_name [type_len] = 0;
9212                         named += type_len;
9213                         /* FIXME: lookup the type and check type consistency */
9214                         g_free (type_name);
9215                 }
9216                 name_len = mono_metadata_decode_blob_size (named, &named);
9217                 name = (char *)g_malloc (name_len + 1);
9218                 memcpy (name, named, name_len);
9219                 name [name_len] = 0;
9220                 named += name_len;
9221                 if (named_type == 0x53) {
9222                         MonoClassField *field;
9223                         void *val;
9224
9225                         /* how this fail is a blackbox */
9226                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9227                         if (!field) {
9228                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9229                                 g_free (name);
9230                                 goto fail;
9231                         }
9232
9233                         val = load_cattr_value (image, field->type, named, &named, error);
9234                         if (!mono_error_ok (error)) {
9235                                 g_free (name);
9236                                 if (!type_is_reference (field->type))
9237                                         g_free (val);
9238                                 goto fail;
9239                         }
9240
9241                         mono_field_set_value (attr, field, val);
9242                         if (!type_is_reference (field->type))
9243                                 g_free (val);
9244                 } else if (named_type == 0x54) {
9245                         MonoProperty *prop;
9246                         void *pparams [1];
9247                         MonoType *prop_type;
9248
9249                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9250
9251                         if (!prop) {
9252                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9253                                 g_free (name);
9254                                 goto fail;
9255                         }
9256
9257                         if (!prop->set) {
9258                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9259                                 g_free (name);
9260                                 goto fail;
9261                         }
9262
9263                         /* can we have more that 1 arg in a custom attr named property? */
9264                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9265                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9266
9267                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9268                         if (!mono_error_ok (error)) {
9269                                 g_free (name);
9270                                 if (!type_is_reference (prop_type))
9271                                         g_free (pparams [0]);
9272                                 goto fail;
9273                         }
9274
9275
9276                         mono_property_set_value (prop, attr, pparams, NULL);
9277                         if (!type_is_reference (prop_type))
9278                                 g_free (pparams [0]);
9279                 }
9280                 g_free (name);
9281         }
9282
9283         free_param_data (method->signature, params);
9284         if (params != params_buf)
9285                 mono_gc_free_fixed (params);
9286
9287         return attr;
9288
9289 fail:
9290         free_param_data (method->signature, params);
9291         if (params != params_buf)
9292                 mono_gc_free_fixed (params);
9293         if (exc)
9294                 mono_raise_exception ((MonoException*)exc);
9295         return NULL;
9296 }
9297         
9298 /*
9299  * mono_reflection_create_custom_attr_data_args:
9300  *
9301  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9302  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9303  * NAMED_ARG_INFO will contain information about the named arguments.
9304  */
9305 void
9306 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)
9307 {
9308         MonoArray *typedargs, *namedargs;
9309         MonoClass *attrklass;
9310         MonoDomain *domain;
9311         const char *p = (const char*)data;
9312         const char *named;
9313         guint32 i, j, num_named;
9314         CattrNamedArg *arginfo = NULL;
9315
9316         *typed_args = NULL;
9317         *named_args = NULL;
9318         *named_arg_info = NULL;
9319
9320         mono_error_init (error);
9321
9322         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9323                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9324                 return;
9325         }
9326
9327         mono_class_init (method->klass);
9328         
9329         domain = mono_domain_get ();
9330
9331         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9332                 return;
9333
9334         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9335         
9336         /* skip prolog */
9337         p += 2;
9338         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9339                 MonoObject *obj;
9340                 void *val;
9341
9342                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9343                 if (!mono_error_ok (error)) {
9344                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9345                                 g_free (val);
9346                         return;
9347                 }
9348
9349                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9350                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9351                 mono_array_setref (typedargs, i, obj);
9352
9353                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9354                         g_free (val);
9355         }
9356
9357         named = p;
9358         num_named = read16 (named);
9359         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9360         named += 2;
9361         attrklass = method->klass;
9362
9363         arginfo = g_new0 (CattrNamedArg, num_named);
9364         *named_arg_info = arginfo;
9365
9366         for (j = 0; j < num_named; j++) {
9367                 gint name_len;
9368                 char *name, named_type, data_type;
9369                 named_type = *named++;
9370                 data_type = *named++; /* type of data */
9371                 if (data_type == MONO_TYPE_SZARRAY)
9372                         data_type = *named++;
9373                 if (data_type == MONO_TYPE_ENUM) {
9374                         gint type_len;
9375                         char *type_name;
9376                         type_len = mono_metadata_decode_blob_size (named, &named);
9377                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9378                                 goto fail;
9379
9380                         type_name = (char *)g_malloc (type_len + 1);
9381                         memcpy (type_name, named, type_len);
9382                         type_name [type_len] = 0;
9383                         named += type_len;
9384                         /* FIXME: lookup the type and check type consistency */
9385                         g_free (type_name);
9386                 }
9387                 name_len = mono_metadata_decode_blob_size (named, &named);
9388                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9389                         goto fail;
9390                 name = (char *)g_malloc (name_len + 1);
9391                 memcpy (name, named, name_len);
9392                 name [name_len] = 0;
9393                 named += name_len;
9394                 if (named_type == 0x53) {
9395                         MonoObject *obj;
9396                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9397                         void *val;
9398
9399                         if (!field) {
9400                                 g_free (name);
9401                                 goto fail;
9402                         }
9403
9404                         arginfo [j].type = field->type;
9405                         arginfo [j].field = field;
9406
9407                         val = load_cattr_value (image, field->type, named, &named, error);
9408                         if (!mono_error_ok (error)) {
9409                                 if (!type_is_reference (field->type))
9410                                         g_free (val);
9411                                 g_free (name);
9412                                 return;
9413                         }
9414
9415                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9416                         mono_array_setref (namedargs, j, obj);
9417                         if (!type_is_reference (field->type))
9418                                 g_free (val);
9419                 } else if (named_type == 0x54) {
9420                         MonoObject *obj;
9421                         MonoType *prop_type;
9422                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9423                         void *val;
9424
9425                         if (!prop || !prop->set) {
9426                                 g_free (name);
9427                                 goto fail;
9428                         }
9429
9430                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9431                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9432
9433                         arginfo [j].type = prop_type;
9434                         arginfo [j].prop = prop;
9435
9436                         val = load_cattr_value (image, prop_type, named, &named, error);
9437                         if (!mono_error_ok (error)) {
9438                                 if (!type_is_reference (prop_type))
9439                                         g_free (val);
9440                                 g_free (name);
9441                                 return;
9442                         }
9443
9444                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9445                         mono_array_setref (namedargs, j, obj);
9446                         if (!type_is_reference (prop_type))
9447                                 g_free (val);
9448                 }
9449                 g_free (name);
9450         }
9451
9452         *typed_args = typedargs;
9453         *named_args = namedargs;
9454         return;
9455 fail:
9456         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9457         g_free (arginfo);
9458         *named_arg_info = NULL;
9459 }
9460
9461 void
9462 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9463 {
9464         MonoDomain *domain;
9465         MonoArray *typedargs, *namedargs;
9466         MonoImage *image;
9467         MonoMethod *method;
9468         CattrNamedArg *arginfo = NULL;
9469         MonoError error;
9470         int i;
9471
9472         mono_error_init (&error);
9473
9474         *ctor_args = NULL;
9475         *named_args = NULL;
9476
9477         if (len == 0)
9478                 return;
9479
9480         image = assembly->assembly->image;
9481         method = ref_method->method;
9482         domain = mono_object_domain (ref_method);
9483
9484         if (!mono_class_init (method->klass))
9485                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9486
9487         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9488         if (!mono_error_ok (&error))
9489                 goto leave;
9490
9491         if (mono_loader_get_last_error ()) {
9492                 mono_error_set_from_loader_error (&error);
9493                 goto leave;
9494         }
9495
9496         if (!typedargs || !namedargs)
9497                 goto leave;
9498
9499         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9500                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9501                 MonoObject *typedarg;
9502
9503                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9504                 if (!is_ok (&error))
9505                         goto leave;
9506                 mono_array_setref (typedargs, i, typedarg);
9507         }
9508
9509         for (i = 0; i < mono_array_length (namedargs); ++i) {
9510                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9511                 MonoObject *typedarg, *namedarg, *minfo;
9512
9513                 if (arginfo [i].prop) {
9514                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9515                         if (!minfo)
9516                                 goto leave;
9517                 } else {
9518                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9519                         if (!mono_error_ok (&error))
9520                                 goto leave;
9521                 }
9522
9523                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9524                 if (!is_ok (&error))
9525                         goto leave;
9526                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9527                 if (!is_ok (&error))
9528                         goto leave;
9529
9530                 mono_array_setref (namedargs, i, namedarg);
9531         }
9532
9533         *ctor_args = typedargs;
9534         *named_args = namedargs;
9535 leave:
9536         g_free (arginfo);
9537         mono_error_raise_exception (&error);
9538
9539 }
9540
9541 static MonoObject*
9542 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9543 {
9544         static MonoMethod *ctor;
9545
9546         MonoDomain *domain;
9547         MonoObject *attr;
9548         void *params [4];
9549
9550         mono_error_init (error);
9551
9552         g_assert (image->assembly);
9553
9554         if (!ctor)
9555                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9556
9557         domain = mono_domain_get ();
9558         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9559         return_val_if_nok (error, NULL);
9560         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9561         return_val_if_nok (error, NULL);
9562         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9563         return_val_if_nok (error, NULL);
9564         params [2] = (gpointer)&cattr->data;
9565         params [3] = &cattr->data_size;
9566
9567         mono_runtime_invoke_checked (ctor, attr, params, error);
9568         return_val_if_nok (error, NULL);
9569         return attr;
9570 }
9571
9572 static MonoArray*
9573 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9574 {
9575         MonoArray *result;
9576         MonoObject *attr;
9577         int i, n;
9578
9579         mono_error_init (error);
9580
9581         n = 0;
9582         for (i = 0; i < cinfo->num_attrs; ++i) {
9583                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9584                         n ++;
9585         }
9586
9587         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9588         n = 0;
9589         for (i = 0; i < cinfo->num_attrs; ++i) {
9590                 if (!cinfo->attrs [i].ctor) {
9591                         /* The cattr type is not finished yet */
9592                         /* We should include the type name but cinfo doesn't contain it */
9593                         mono_error_set_type_load_name (error, NULL, NULL, "");
9594                         return NULL;
9595                 }
9596                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9597                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9598                         if (!mono_error_ok (error))
9599                                 return result;
9600                         mono_array_setref (result, n, attr);
9601                         n ++;
9602                 }
9603         }
9604         return result;
9605 }
9606
9607 MonoArray*
9608 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9609 {
9610         MonoError error;
9611         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9612         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9613
9614         return result;
9615 }
9616
9617 static MonoArray*
9618 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9619 {
9620         MonoArray *result;
9621         MonoObject *attr;
9622         int i;
9623         
9624         mono_error_init (error);
9625         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9626         for (i = 0; i < cinfo->num_attrs; ++i) {
9627                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9628                 return_val_if_nok (error, NULL);
9629                 mono_array_setref (result, i, attr);
9630         }
9631         return result;
9632 }
9633
9634 /**
9635  * mono_custom_attrs_from_index:
9636  *
9637  * Returns: NULL if no attributes are found or if a loading error occurs.
9638  */
9639 MonoCustomAttrInfo*
9640 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9641 {
9642         MonoError error;
9643         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9644         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9645         return result;
9646 }
9647 /**
9648  * mono_custom_attrs_from_index_checked:
9649  *
9650  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9651  */
9652 MonoCustomAttrInfo*
9653 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9654 {
9655         guint32 mtoken, i, len;
9656         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9657         MonoTableInfo *ca;
9658         MonoCustomAttrInfo *ainfo;
9659         GList *tmp, *list = NULL;
9660         const char *data;
9661         MonoCustomAttrEntry* attr;
9662
9663         mono_error_init (error);
9664
9665         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9666
9667         i = mono_metadata_custom_attrs_from_index (image, idx);
9668         if (!i)
9669                 return NULL;
9670         i --;
9671         while (i < ca->rows) {
9672                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9673                         break;
9674                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9675                 ++i;
9676         }
9677         len = g_list_length (list);
9678         if (!len)
9679                 return NULL;
9680         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9681         ainfo->num_attrs = len;
9682         ainfo->image = image;
9683         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9684                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9685                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9686                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9687                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9688                         mtoken |= MONO_TOKEN_METHOD_DEF;
9689                         break;
9690                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9691                         mtoken |= MONO_TOKEN_MEMBER_REF;
9692                         break;
9693                 default:
9694                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9695                         break;
9696                 }
9697                 attr = &ainfo->attrs [i - 1];
9698                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9699                 if (!attr->ctor) {
9700                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9701                         g_list_free (list);
9702                         g_free (ainfo);
9703                         return NULL;
9704                 }
9705
9706                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9707                         /*FIXME raising an exception here doesn't make any sense*/
9708                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9709                         g_list_free (list);
9710                         g_free (ainfo);
9711                         return NULL;
9712                 }
9713                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9714                 attr->data_size = mono_metadata_decode_value (data, &data);
9715                 attr->data = (guchar*)data;
9716         }
9717         g_list_free (list);
9718
9719         return ainfo;
9720 }
9721
9722 MonoCustomAttrInfo*
9723 mono_custom_attrs_from_method (MonoMethod *method)
9724 {
9725         MonoError error;
9726         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9727         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9728         return result;
9729 }
9730
9731 MonoCustomAttrInfo*
9732 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9733 {
9734         guint32 idx;
9735
9736         mono_error_init (error);
9737
9738         /*
9739          * An instantiated method has the same cattrs as the generic method definition.
9740          *
9741          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9742          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9743          */
9744         if (method->is_inflated)
9745                 method = ((MonoMethodInflated *) method)->declaring;
9746         
9747         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9748                 return lookup_custom_attr (method->klass->image, method);
9749
9750         if (!method->token)
9751                 /* Synthetic methods */
9752                 return NULL;
9753
9754         idx = mono_method_get_index (method);
9755         idx <<= MONO_CUSTOM_ATTR_BITS;
9756         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9757         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9758 }
9759
9760 MonoCustomAttrInfo*
9761 mono_custom_attrs_from_class (MonoClass *klass)
9762 {
9763         MonoError error;
9764         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9765         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9766         return result;
9767 }
9768
9769 MonoCustomAttrInfo*
9770 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9771 {
9772         guint32 idx;
9773
9774         mono_error_init (error);
9775
9776         if (klass->generic_class)
9777                 klass = klass->generic_class->container_class;
9778
9779         if (image_is_dynamic (klass->image))
9780                 return lookup_custom_attr (klass->image, klass);
9781
9782         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9783                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9784                 idx <<= MONO_CUSTOM_ATTR_BITS;
9785                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9786         } else {
9787                 idx = mono_metadata_token_index (klass->type_token);
9788                 idx <<= MONO_CUSTOM_ATTR_BITS;
9789                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9790         }
9791         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9792 }
9793
9794 MonoCustomAttrInfo*
9795 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9796 {
9797         MonoError error;
9798         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9799         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9800         return result;
9801 }
9802
9803 MonoCustomAttrInfo*
9804 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9805 {
9806         guint32 idx;
9807         
9808         mono_error_init (error);
9809
9810         if (image_is_dynamic (assembly->image))
9811                 return lookup_custom_attr (assembly->image, assembly);
9812         idx = 1; /* there is only one assembly */
9813         idx <<= MONO_CUSTOM_ATTR_BITS;
9814         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9815         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9816 }
9817
9818 static MonoCustomAttrInfo*
9819 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9820 {
9821         guint32 idx;
9822         
9823         if (image_is_dynamic (image))
9824                 return lookup_custom_attr (image, image);
9825         idx = 1; /* there is only one module */
9826         idx <<= MONO_CUSTOM_ATTR_BITS;
9827         idx |= MONO_CUSTOM_ATTR_MODULE;
9828         return mono_custom_attrs_from_index_checked (image, idx, error);
9829 }
9830
9831 MonoCustomAttrInfo*
9832 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9833 {
9834         MonoError error;
9835         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9836         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9837         return result;
9838 }
9839
9840 MonoCustomAttrInfo*
9841 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9842 {
9843         guint32 idx;
9844         
9845         if (image_is_dynamic (klass->image)) {
9846                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9847                 return lookup_custom_attr (klass->image, property);
9848         }
9849         idx = find_property_index (klass, property);
9850         idx <<= MONO_CUSTOM_ATTR_BITS;
9851         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9852         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9853 }
9854
9855 MonoCustomAttrInfo*
9856 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9857 {
9858         MonoError error;
9859         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9860         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9861         return result;
9862 }
9863
9864 MonoCustomAttrInfo*
9865 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9866 {
9867         guint32 idx;
9868         
9869         if (image_is_dynamic (klass->image)) {
9870                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9871                 return lookup_custom_attr (klass->image, event);
9872         }
9873         idx = find_event_index (klass, event);
9874         idx <<= MONO_CUSTOM_ATTR_BITS;
9875         idx |= MONO_CUSTOM_ATTR_EVENT;
9876         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9877 }
9878
9879 MonoCustomAttrInfo*
9880 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9881 {
9882         MonoError error;
9883         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9884         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9885         return result;
9886 }
9887
9888 MonoCustomAttrInfo*
9889 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9890 {
9891         guint32 idx;
9892         mono_error_init (error);
9893
9894         if (image_is_dynamic (klass->image)) {
9895                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9896                 return lookup_custom_attr (klass->image, field);
9897         }
9898         idx = find_field_index (klass, field);
9899         idx <<= MONO_CUSTOM_ATTR_BITS;
9900         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9901         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9902 }
9903
9904 /**
9905  * mono_custom_attrs_from_param:
9906  * @method: handle to the method that we want to retrieve custom parameter information from
9907  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9908  *
9909  * The result must be released with mono_custom_attrs_free().
9910  *
9911  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9912  */
9913 MonoCustomAttrInfo*
9914 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9915 {
9916         MonoError error;
9917         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9918         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9919         return result;
9920 }
9921
9922 /**
9923  * mono_custom_attrs_from_param_checked:
9924  * @method: handle to the method that we want to retrieve custom parameter information from
9925  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9926  * @error: set on error
9927  *
9928  * The result must be released with mono_custom_attrs_free().
9929  *
9930  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
9931  */
9932 MonoCustomAttrInfo*
9933 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9934 {
9935         MonoTableInfo *ca;
9936         guint32 i, idx, method_index;
9937         guint32 param_list, param_last, param_pos, found;
9938         MonoImage *image;
9939         MonoReflectionMethodAux *aux;
9940
9941         mono_error_init (error);
9942
9943         /*
9944          * An instantiated method has the same cattrs as the generic method definition.
9945          *
9946          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9947          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9948          */
9949         if (method->is_inflated)
9950                 method = ((MonoMethodInflated *) method)->declaring;
9951
9952         if (image_is_dynamic (method->klass->image)) {
9953                 MonoCustomAttrInfo *res, *ainfo;
9954                 int size;
9955
9956                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9957                 if (!aux || !aux->param_cattr)
9958                         return NULL;
9959
9960                 /* Need to copy since it will be freed later */
9961                 ainfo = aux->param_cattr [param];
9962                 if (!ainfo)
9963                         return NULL;
9964                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9965                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9966                 memcpy (res, ainfo, size);
9967                 return res;
9968         }
9969
9970         image = method->klass->image;
9971         method_index = mono_method_get_index (method);
9972         if (!method_index)
9973                 return NULL;
9974         ca = &image->tables [MONO_TABLE_METHOD];
9975
9976         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9977         if (method_index == ca->rows) {
9978                 ca = &image->tables [MONO_TABLE_PARAM];
9979                 param_last = ca->rows + 1;
9980         } else {
9981                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9982                 ca = &image->tables [MONO_TABLE_PARAM];
9983         }
9984         found = FALSE;
9985         for (i = param_list; i < param_last; ++i) {
9986                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9987                 if (param_pos == param) {
9988                         found = TRUE;
9989                         break;
9990                 }
9991         }
9992         if (!found)
9993                 return NULL;
9994         idx = i;
9995         idx <<= MONO_CUSTOM_ATTR_BITS;
9996         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9997         return mono_custom_attrs_from_index_checked (image, idx, error);
9998 }
9999
10000 gboolean
10001 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10002 {
10003         int i;
10004         MonoClass *klass;
10005         for (i = 0; i < ainfo->num_attrs; ++i) {
10006                 klass = ainfo->attrs [i].ctor->klass;
10007                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10008                         return TRUE;
10009         }
10010         return FALSE;
10011 }
10012
10013 MonoObject*
10014 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10015 {
10016         MonoError error;
10017         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10018         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10019         return res;
10020 }
10021
10022 MonoObject*
10023 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10024 {
10025         int i, attr_index;
10026         MonoClass *klass;
10027         MonoArray *attrs;
10028
10029         mono_error_init (error);
10030
10031         attr_index = -1;
10032         for (i = 0; i < ainfo->num_attrs; ++i) {
10033                 klass = ainfo->attrs [i].ctor->klass;
10034                 if (mono_class_has_parent (klass, attr_klass)) {
10035                         attr_index = i;
10036                         break;
10037                 }
10038         }
10039         if (attr_index == -1)
10040                 return NULL;
10041
10042         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10043         if (!mono_error_ok (error))
10044                 return NULL;
10045         return mono_array_get (attrs, MonoObject*, attr_index);
10046 }
10047
10048 /*
10049  * mono_reflection_get_custom_attrs_info:
10050  * @obj: a reflection object handle
10051  *
10052  * Return the custom attribute info for attributes defined for the
10053  * reflection handle @obj. The objects.
10054  *
10055  * FIXME this function leaks like a sieve for SRE objects.
10056  */
10057 MonoCustomAttrInfo*
10058 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10059 {
10060         MonoError error;
10061         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10062         mono_error_assert_ok (&error);
10063         return result;
10064 }
10065
10066 /**
10067  * mono_reflection_get_custom_attrs_info_checked:
10068  * @obj: a reflection object handle
10069  * @error: set on error
10070  *
10071  * Return the custom attribute info for attributes defined for the
10072  * reflection handle @obj. The objects.
10073  *
10074  * On failure returns NULL and sets @error.
10075  *
10076  * FIXME this function leaks like a sieve for SRE objects.
10077  */
10078 MonoCustomAttrInfo*
10079 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10080 {
10081         MonoClass *klass;
10082         MonoCustomAttrInfo *cinfo = NULL;
10083         
10084         mono_error_init (error);
10085
10086         klass = obj->vtable->klass;
10087         if (klass == mono_defaults.monotype_class) {
10088                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10089                 return_val_if_nok (error, NULL);
10090                 klass = mono_class_from_mono_type (type);
10091                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10092                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10093                 return_val_if_nok (error, NULL);
10094         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10095                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10096                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10097                 return_val_if_nok (error, NULL);
10098         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10099                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10100                 cinfo = mono_custom_attrs_from_module (module->image, error);
10101                 return_val_if_nok (error, NULL);
10102         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10103                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10104                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10105                 return_val_if_nok (error, NULL);
10106         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10107                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10108                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10109                 return_val_if_nok (error, NULL);
10110         } else if (strcmp ("MonoField", klass->name) == 0) {
10111                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10112                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10113                 return_val_if_nok (error, NULL);
10114         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10115                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10116                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10117                 return_val_if_nok (error, NULL);
10118         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10119                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10120                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10121                 return_val_if_nok (error, NULL);
10122         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10123                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10124                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10125                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10126                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10127                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10128                         return_val_if_nok (error, NULL);
10129                 } else if (is_sr_mono_property (member_class)) {
10130                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10131                         MonoMethod *method;
10132                         if (!(method = prop->property->get))
10133                                 method = prop->property->set;
10134                         g_assert (method);
10135
10136                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10137                         return_val_if_nok (error, NULL);
10138                 } 
10139 #ifndef DISABLE_REFLECTION_EMIT
10140                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10141                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10142                         return_val_if_nok (error, NULL);
10143                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10144                         return_val_if_nok (error, NULL);
10145                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10146                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10147                         MonoMethod *method = NULL;
10148                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10149                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10150                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10151                                 method = ((MonoReflectionMethod *)c->cb)->method;
10152                         else
10153                                 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));
10154
10155                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10156                         return_val_if_nok (error, NULL);
10157                 } 
10158 #endif
10159                 else {
10160                         char *type_name = mono_type_get_full_name (member_class);
10161                         mono_error_set_generic_error (error, "System", "NotSupportedException",
10162                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10163                                                       type_name);
10164                         g_free (type_name);
10165                         return NULL;
10166                 }
10167         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10168                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10169                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10170         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10171                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10172                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10173         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10174                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10175                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10176         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10177                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10178                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10179         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10180                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10181                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10182         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10183                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10184                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10185         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10186                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10187                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10188                 return_val_if_nok (error, NULL);
10189         } else { /* handle other types here... */
10190                 g_error ("get custom attrs not yet supported for %s", klass->name);
10191         }
10192
10193         return cinfo;
10194 }
10195
10196 /*
10197  * mono_reflection_get_custom_attrs_by_type:
10198  * @obj: a reflection object handle
10199  *
10200  * Return an array with all the custom attributes defined of the
10201  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10202  * of that type are returned. The objects are fully build. Return NULL if a loading error
10203  * occurs.
10204  */
10205 MonoArray*
10206 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10207 {
10208         MonoArray *result;
10209         MonoCustomAttrInfo *cinfo;
10210
10211         mono_error_init (error);
10212
10213         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10214         return_val_if_nok (error, NULL);
10215         if (cinfo) {
10216                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10217                 if (!result)
10218                         return NULL;
10219                 if (!cinfo->cached)
10220                         mono_custom_attrs_free (cinfo);
10221         } else {
10222                 mono_loader_assert_no_error ();
10223                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10224         }
10225
10226         return result;
10227 }
10228
10229 /*
10230  * mono_reflection_get_custom_attrs:
10231  * @obj: a reflection object handle
10232  *
10233  * Return an array with all the custom attributes defined of the
10234  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10235  * occurs.
10236  */
10237 MonoArray*
10238 mono_reflection_get_custom_attrs (MonoObject *obj)
10239 {
10240         MonoError error;
10241
10242         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10243 }
10244
10245 /*
10246  * mono_reflection_get_custom_attrs_data:
10247  * @obj: a reflection obj handle
10248  *
10249  * Returns an array of System.Reflection.CustomAttributeData,
10250  * which include information about attributes reflected on
10251  * types loaded using the Reflection Only methods
10252  */
10253 MonoArray*
10254 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10255 {
10256         MonoError error;
10257         MonoArray* result;
10258         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10259         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10260         return result;
10261 }
10262
10263 /*
10264  * mono_reflection_get_custom_attrs_data_checked:
10265  * @obj: a reflection obj handle
10266  * @error: set on error
10267  *
10268  * Returns an array of System.Reflection.CustomAttributeData,
10269  * which include information about attributes reflected on
10270  * types loaded using the Reflection Only methods
10271  */
10272 MonoArray*
10273 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10274 {
10275         MonoArray *result;
10276         MonoCustomAttrInfo *cinfo;
10277
10278         mono_error_init (error);
10279
10280         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10281         return_val_if_nok (error, NULL);
10282         if (cinfo) {
10283                 result = mono_custom_attrs_data_construct (cinfo, error);
10284                 return_val_if_nok (error, NULL);
10285                 if (!cinfo->cached)
10286                         mono_custom_attrs_free (cinfo);
10287         } else
10288                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10289
10290         if (mono_loader_get_last_error ())
10291                 mono_error_set_from_loader_error (error);
10292
10293         return result;
10294 }
10295
10296 static MonoReflectionType*
10297 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10298 {
10299         static MonoMethod *method_get_underlying_system_type = NULL;
10300         MonoReflectionType *rt;
10301         MonoMethod *usertype_method;
10302
10303         mono_error_init (error);
10304
10305         if (!method_get_underlying_system_type)
10306                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10307
10308         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10309
10310         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10311
10312         return rt;
10313 }
10314
10315
10316 static gboolean
10317 is_corlib_type (MonoClass *klass)
10318 {
10319         return klass->image == mono_defaults.corlib;
10320 }
10321
10322 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10323         static MonoClass *cached_class; \
10324         if (cached_class) \
10325                 return cached_class == _class; \
10326         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10327                 cached_class = _class; \
10328                 return TRUE; \
10329         } \
10330         return FALSE; \
10331 } while (0) \
10332
10333
10334 #ifndef DISABLE_REFLECTION_EMIT
10335 static gboolean
10336 is_sre_array (MonoClass *klass)
10337 {
10338         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10339 }
10340
10341 static gboolean
10342 is_sre_byref (MonoClass *klass)
10343 {
10344         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10345 }
10346
10347 static gboolean
10348 is_sre_pointer (MonoClass *klass)
10349 {
10350         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10351 }
10352
10353 static gboolean
10354 is_sre_generic_instance (MonoClass *klass)
10355 {
10356         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10357 }
10358
10359 static gboolean
10360 is_sre_type_builder (MonoClass *klass)
10361 {
10362         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10363 }
10364
10365 static gboolean
10366 is_sre_method_builder (MonoClass *klass)
10367 {
10368         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10369 }
10370
10371 static gboolean
10372 is_sre_ctor_builder (MonoClass *klass)
10373 {
10374         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10375 }
10376
10377 static gboolean
10378 is_sre_field_builder (MonoClass *klass)
10379 {
10380         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10381 }
10382
10383 static gboolean
10384 is_sre_method_on_tb_inst (MonoClass *klass)
10385 {
10386         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10387 }
10388
10389 static gboolean
10390 is_sre_ctor_on_tb_inst (MonoClass *klass)
10391 {
10392         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10393 }
10394
10395 MonoType*
10396 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10397 {
10398         MonoClass *klass;
10399         mono_error_init (error);
10400
10401         if (!ref)
10402                 return NULL;
10403         if (ref->type)
10404                 return ref->type;
10405
10406         if (is_usertype (ref)) {
10407                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10408                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10409                         return NULL;
10410                 if (ref->type)
10411                         return ref->type;
10412         }
10413
10414         klass = mono_object_class (ref);
10415
10416         if (is_sre_array (klass)) {
10417                 MonoType *res;
10418                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10419                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10420                 return_val_if_nok (error, NULL);
10421                 g_assert (base);
10422                 if (sre_array->rank == 0) //single dimentional array
10423                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10424                 else
10425                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10426                 sre_array->type.type = res;
10427                 return res;
10428         } else if (is_sre_byref (klass)) {
10429                 MonoType *res;
10430                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10431                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10432                 return_val_if_nok (error, NULL);
10433                 g_assert (base);
10434                 res = &mono_class_from_mono_type (base)->this_arg;
10435                 sre_byref->type.type = res;
10436                 return res;
10437         } else if (is_sre_pointer (klass)) {
10438                 MonoType *res;
10439                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10440                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10441                 return_val_if_nok (error, NULL);
10442                 g_assert (base);
10443                 res = &mono_ptr_class_get (base)->byval_arg;
10444                 sre_pointer->type.type = res;
10445                 return res;
10446         } else if (is_sre_generic_instance (klass)) {
10447                 MonoType *res, **types;
10448                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10449                 int i, count;
10450
10451                 count = mono_array_length (gclass->type_arguments);
10452                 types = g_new0 (MonoType*, count);
10453                 for (i = 0; i < count; ++i) {
10454                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10455                         types [i] = mono_reflection_type_get_handle (t, error);
10456                         if (!types[i] || !is_ok (error)) {
10457                                 g_free (types);
10458                                 return NULL;
10459                         }
10460                 }
10461
10462                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10463                 g_free (types);
10464                 g_assert (res);
10465                 gclass->type.type = res;
10466                 return res;
10467         }
10468
10469         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10470         return NULL;
10471 }
10472
10473 void
10474 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10475 {
10476         MonoError error;
10477         mono_reflection_type_get_handle (type, &error);
10478         mono_error_set_pending_exception (&error);
10479 }
10480
10481 void
10482 mono_reflection_register_with_runtime (MonoReflectionType *type)
10483 {
10484         MonoError error;
10485         MonoType *res = mono_reflection_type_get_handle (type, &error);
10486         mono_error_raise_exception (&error); /* FIXME don't raise here */
10487         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10488         MonoClass *klass;
10489
10490         if (!res)
10491                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10492
10493         klass = mono_class_from_mono_type (res);
10494
10495         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10496         mono_domain_lock (domain);
10497
10498         if (!image_is_dynamic (klass->image)) {
10499                 mono_class_setup_supertypes (klass);
10500         } else {
10501                 if (!domain->type_hash)
10502                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10503                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10504                 mono_g_hash_table_insert (domain->type_hash, res, type);
10505         }
10506         mono_domain_unlock (domain);
10507         mono_loader_unlock ();
10508 }
10509
10510 /**
10511  * LOCKING: Assumes the loader lock is held.
10512  */
10513 static MonoMethodSignature*
10514 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10515         MonoError error;
10516         MonoMethodSignature *sig;
10517         int count, i;
10518
10519         count = parameters? mono_array_length (parameters): 0;
10520
10521         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10522         sig->param_count = count;
10523         sig->sentinelpos = -1; /* FIXME */
10524         for (i = 0; i < count; ++i) {
10525                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10526                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10527         }
10528         return sig;
10529 }
10530
10531 /**
10532  * LOCKING: Assumes the loader lock is held.
10533  */
10534 static MonoMethodSignature*
10535 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10536         MonoMethodSignature *sig;
10537
10538         sig = parameters_to_signature (image, ctor->parameters);
10539         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10540         sig->ret = &mono_defaults.void_class->byval_arg;
10541         return sig;
10542 }
10543
10544 /**
10545  * LOCKING: Assumes the loader lock is held.
10546  */
10547 static MonoMethodSignature*
10548 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10549         MonoError error;
10550         MonoMethodSignature *sig;
10551
10552         sig = parameters_to_signature (image, method->parameters);
10553         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10554         if (method->rtype) {
10555                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10556                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10557         } else {
10558                 sig->ret = &mono_defaults.void_class->byval_arg;
10559         }
10560         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10561         return sig;
10562 }
10563
10564 static MonoMethodSignature*
10565 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10566         MonoError error;
10567         MonoMethodSignature *sig;
10568
10569         sig = parameters_to_signature (NULL, method->parameters);
10570         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10571         if (method->rtype) {
10572                 sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
10573                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10574         } else {
10575                 sig->ret = &mono_defaults.void_class->byval_arg;
10576         }
10577         sig->generic_param_count = 0;
10578         return sig;
10579 }
10580
10581 static void
10582 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10583 {
10584         MonoError error;
10585         MonoClass *klass = mono_object_class (prop);
10586         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10587                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10588                 *name = mono_string_to_utf8 (pb->name);
10589                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10590                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10591         } else {
10592                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10593                 *name = g_strdup (p->property->name);
10594                 if (p->property->get)
10595                         *type = mono_method_signature (p->property->get)->ret;
10596                 else
10597                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10598         }
10599 }
10600
10601 static void
10602 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10603 {
10604         MonoError error;
10605         MonoClass *klass = mono_object_class (field);
10606         if (strcmp (klass->name, "FieldBuilder") == 0) {
10607                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10608                 *name = mono_string_to_utf8 (fb->name);
10609                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10610                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10611         } else {
10612                 MonoReflectionField *f = (MonoReflectionField *)field;
10613                 *name = g_strdup (mono_field_get_name (f->field));
10614                 *type = f->field->type;
10615         }
10616 }
10617
10618 #else /* DISABLE_REFLECTION_EMIT */
10619
10620 void
10621 mono_reflection_register_with_runtime (MonoReflectionType *type)
10622 {
10623         /* This is empty */
10624 }
10625
10626 static gboolean
10627 is_sre_type_builder (MonoClass *klass)
10628 {
10629         return FALSE;
10630 }
10631
10632 static gboolean
10633 is_sre_generic_instance (MonoClass *klass)
10634 {
10635         return FALSE;
10636 }
10637
10638 static void
10639 init_type_builder_generics (MonoObject *type)
10640 {
10641 }
10642
10643 #endif /* !DISABLE_REFLECTION_EMIT */
10644
10645
10646 static gboolean
10647 is_sr_mono_field (MonoClass *klass)
10648 {
10649         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10650 }
10651
10652 static gboolean
10653 is_sr_mono_property (MonoClass *klass)
10654 {
10655         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10656 }
10657
10658 static gboolean
10659 is_sr_mono_method (MonoClass *klass)
10660 {
10661         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10662 }
10663
10664 static gboolean
10665 is_sr_mono_cmethod (MonoClass *klass)
10666 {
10667         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10668 }
10669
10670 static gboolean
10671 is_sr_mono_generic_method (MonoClass *klass)
10672 {
10673         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10674 }
10675
10676 static gboolean
10677 is_sr_mono_generic_cmethod (MonoClass *klass)
10678 {
10679         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10680 }
10681
10682 gboolean
10683 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10684 {
10685         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10686 }
10687
10688 static gboolean
10689 is_usertype (MonoReflectionType *ref)
10690 {
10691         MonoClass *klass = mono_object_class (ref);
10692         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10693 }
10694
10695 static MonoReflectionType*
10696 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10697 {
10698         mono_error_init (error);
10699         if (!type || type->type)
10700                 return type;
10701
10702         if (is_usertype (type)) {
10703                 type = mono_reflection_type_get_underlying_system_type (type, error);
10704                 return_val_if_nok (error, NULL);
10705                 if (is_usertype (type)) {
10706                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10707                         return NULL;
10708                 }
10709         }
10710
10711         return type;
10712 }
10713 /*
10714  * Encode a value in a custom attribute stream of bytes.
10715  * The value to encode is either supplied as an object in argument val
10716  * (valuetypes are boxed), or as a pointer to the data in the
10717  * argument argval.
10718  * @type represents the type of the value
10719  * @buffer is the start of the buffer
10720  * @p the current position in the buffer
10721  * @buflen contains the size of the buffer and is used to return the new buffer size
10722  * if this needs to be realloced.
10723  * @retbuffer and @retp return the start and the position of the buffer
10724  */
10725 static void
10726 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10727 {
10728         MonoError error;
10729         MonoTypeEnum simple_type;
10730         
10731         if ((p-buffer) + 10 >= *buflen) {
10732                 char *newbuf;
10733                 *buflen *= 2;
10734                 newbuf = (char *)g_realloc (buffer, *buflen);
10735                 p = newbuf + (p-buffer);
10736                 buffer = newbuf;
10737         }
10738         if (!argval)
10739                 argval = ((char*)arg + sizeof (MonoObject));
10740         simple_type = type->type;
10741 handle_enum:
10742         switch (simple_type) {
10743         case MONO_TYPE_BOOLEAN:
10744         case MONO_TYPE_U1:
10745         case MONO_TYPE_I1:
10746                 *p++ = *argval;
10747                 break;
10748         case MONO_TYPE_CHAR:
10749         case MONO_TYPE_U2:
10750         case MONO_TYPE_I2:
10751                 swap_with_size (p, argval, 2, 1);
10752                 p += 2;
10753                 break;
10754         case MONO_TYPE_U4:
10755         case MONO_TYPE_I4:
10756         case MONO_TYPE_R4:
10757                 swap_with_size (p, argval, 4, 1);
10758                 p += 4;
10759                 break;
10760         case MONO_TYPE_R8:
10761                 swap_with_size (p, argval, 8, 1);
10762                 p += 8;
10763                 break;
10764         case MONO_TYPE_U8:
10765         case MONO_TYPE_I8:
10766                 swap_with_size (p, argval, 8, 1);
10767                 p += 8;
10768                 break;
10769         case MONO_TYPE_VALUETYPE:
10770                 if (type->data.klass->enumtype) {
10771                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10772                         goto handle_enum;
10773                 } else {
10774                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10775                 }
10776                 break;
10777         case MONO_TYPE_STRING: {
10778                 char *str;
10779                 guint32 slen;
10780                 if (!arg) {
10781                         *p++ = 0xFF;
10782                         break;
10783                 }
10784                 str = mono_string_to_utf8 ((MonoString*)arg);
10785                 slen = strlen (str);
10786                 if ((p-buffer) + 10 + slen >= *buflen) {
10787                         char *newbuf;
10788                         *buflen *= 2;
10789                         *buflen += slen;
10790                         newbuf = (char *)g_realloc (buffer, *buflen);
10791                         p = newbuf + (p-buffer);
10792                         buffer = newbuf;
10793                 }
10794                 mono_metadata_encode_value (slen, p, &p);
10795                 memcpy (p, str, slen);
10796                 p += slen;
10797                 g_free (str);
10798                 break;
10799         }
10800         case MONO_TYPE_CLASS: {
10801                 char *str;
10802                 guint32 slen;
10803                 MonoType *arg_type;
10804                 if (!arg) {
10805                         *p++ = 0xFF;
10806                         break;
10807                 }
10808 handle_type:
10809                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10810                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10811                 str = type_get_qualified_name (arg_type, NULL);
10812                 slen = strlen (str);
10813                 if ((p-buffer) + 10 + slen >= *buflen) {
10814                         char *newbuf;
10815                         *buflen *= 2;
10816                         *buflen += slen;
10817                         newbuf = (char *)g_realloc (buffer, *buflen);
10818                         p = newbuf + (p-buffer);
10819                         buffer = newbuf;
10820                 }
10821                 mono_metadata_encode_value (slen, p, &p);
10822                 memcpy (p, str, slen);
10823                 p += slen;
10824                 g_free (str);
10825                 break;
10826         }
10827         case MONO_TYPE_SZARRAY: {
10828                 int len, i;
10829                 MonoClass *eclass, *arg_eclass;
10830
10831                 if (!arg) {
10832                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10833                         break;
10834                 }
10835                 len = mono_array_length ((MonoArray*)arg);
10836                 *p++ = len & 0xff;
10837                 *p++ = (len >> 8) & 0xff;
10838                 *p++ = (len >> 16) & 0xff;
10839                 *p++ = (len >> 24) & 0xff;
10840                 *retp = p;
10841                 *retbuffer = buffer;
10842                 eclass = type->data.klass;
10843                 arg_eclass = mono_object_class (arg)->element_class;
10844
10845                 if (!eclass) {
10846                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10847                         eclass = mono_defaults.object_class;
10848                 }
10849                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10850                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10851                         int elsize = mono_class_array_element_size (arg_eclass);
10852                         for (i = 0; i < len; ++i) {
10853                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10854                                 elptr += elsize;
10855                         }
10856                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10857                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10858                         int elsize = mono_class_array_element_size (eclass);
10859                         for (i = 0; i < len; ++i) {
10860                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10861                                 elptr += elsize;
10862                         }
10863                 } else {
10864                         for (i = 0; i < len; ++i) {
10865                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10866                         }
10867                 }
10868                 break;
10869         }
10870         case MONO_TYPE_OBJECT: {
10871                 MonoClass *klass;
10872                 char *str;
10873                 guint32 slen;
10874
10875                 /*
10876                  * The parameter type is 'object' but the type of the actual
10877                  * argument is not. So we have to add type information to the blob
10878                  * too. This is completely undocumented in the spec.
10879                  */
10880
10881                 if (arg == NULL) {
10882                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10883                         *p++ = 0xFF;
10884                         break;
10885                 }
10886                 
10887                 klass = mono_object_class (arg);
10888
10889                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10890                         *p++ = 0x50;
10891                         goto handle_type;
10892                 } else if (klass->enumtype) {
10893                         *p++ = 0x55;
10894                 } else if (klass == mono_defaults.string_class) {
10895                         simple_type = MONO_TYPE_STRING;
10896                         *p++ = 0x0E;
10897                         goto handle_enum;
10898                 } else if (klass->rank == 1) {
10899                         *p++ = 0x1D;
10900                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10901                                 /* See Partition II, Appendix B3 */
10902                                 *p++ = 0x51;
10903                         else
10904                                 *p++ = klass->element_class->byval_arg.type;
10905                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10906                         break;
10907                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10908                         *p++ = simple_type = klass->byval_arg.type;
10909                         goto handle_enum;
10910                 } else {
10911                         g_error ("unhandled type in custom attr");
10912                 }
10913                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10914                 slen = strlen (str);
10915                 if ((p-buffer) + 10 + slen >= *buflen) {
10916                         char *newbuf;
10917                         *buflen *= 2;
10918                         *buflen += slen;
10919                         newbuf = (char *)g_realloc (buffer, *buflen);
10920                         p = newbuf + (p-buffer);
10921                         buffer = newbuf;
10922                 }
10923                 mono_metadata_encode_value (slen, p, &p);
10924                 memcpy (p, str, slen);
10925                 p += slen;
10926                 g_free (str);
10927                 simple_type = mono_class_enum_basetype (klass)->type;
10928                 goto handle_enum;
10929         }
10930         default:
10931                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10932         }
10933         *retp = p;
10934         *retbuffer = buffer;
10935 }
10936
10937 static void
10938 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10939 {
10940         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10941                 char *str = type_get_qualified_name (type, NULL);
10942                 int slen = strlen (str);
10943
10944                 *p++ = 0x55;
10945                 /*
10946                  * This seems to be optional...
10947                  * *p++ = 0x80;
10948                  */
10949                 mono_metadata_encode_value (slen, p, &p);
10950                 memcpy (p, str, slen);
10951                 p += slen;
10952                 g_free (str);
10953         } else if (type->type == MONO_TYPE_OBJECT) {
10954                 *p++ = 0x51;
10955         } else if (type->type == MONO_TYPE_CLASS) {
10956                 /* it should be a type: encode_cattr_value () has the check */
10957                 *p++ = 0x50;
10958         } else {
10959                 mono_metadata_encode_value (type->type, p, &p);
10960                 if (type->type == MONO_TYPE_SZARRAY)
10961                         /* See the examples in Partition VI, Annex B */
10962                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10963         }
10964
10965         *retp = p;
10966 }
10967
10968 #ifndef DISABLE_REFLECTION_EMIT
10969 static void
10970 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10971 {
10972         int len;
10973         /* Preallocate a large enough buffer */
10974         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10975                 char *str = type_get_qualified_name (type, NULL);
10976                 len = strlen (str);
10977                 g_free (str);
10978         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10979                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10980                 len = strlen (str);
10981                 g_free (str);
10982         } else {
10983                 len = 0;
10984         }
10985         len += strlen (name);
10986
10987         if ((p-buffer) + 20 + len >= *buflen) {
10988                 char *newbuf;
10989                 *buflen *= 2;
10990                 *buflen += len;
10991                 newbuf = (char *)g_realloc (buffer, *buflen);
10992                 p = newbuf + (p-buffer);
10993                 buffer = newbuf;
10994         }
10995
10996         encode_field_or_prop_type (type, p, &p);
10997
10998         len = strlen (name);
10999         mono_metadata_encode_value (len, p, &p);
11000         memcpy (p, name, len);
11001         p += len;
11002         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11003         *retp = p;
11004         *retbuffer = buffer;
11005 }
11006
11007 /*
11008  * mono_reflection_get_custom_attrs_blob:
11009  * @ctor: custom attribute constructor
11010  * @ctorArgs: arguments o the constructor
11011  * @properties:
11012  * @propValues:
11013  * @fields:
11014  * @fieldValues:
11015  * 
11016  * Creates the blob of data that needs to be saved in the metadata and that represents
11017  * the custom attributed described by @ctor, @ctorArgs etc.
11018  * Returns: a Byte array representing the blob of data.
11019  */
11020 MonoArray*
11021 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11022 {
11023         MonoArray *result;
11024         MonoMethodSignature *sig;
11025         MonoObject *arg;
11026         char *buffer, *p;
11027         guint32 buflen, i;
11028
11029         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11030                 /* sig is freed later so allocate it in the heap */
11031                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11032         } else {
11033                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11034         }
11035
11036         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11037         buflen = 256;
11038         p = buffer = (char *)g_malloc (buflen);
11039         /* write the prolog */
11040         *p++ = 1;
11041         *p++ = 0;
11042         for (i = 0; i < sig->param_count; ++i) {
11043                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11044                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11045         }
11046         i = 0;
11047         if (properties)
11048                 i += mono_array_length (properties);
11049         if (fields)
11050                 i += mono_array_length (fields);
11051         *p++ = i & 0xff;
11052         *p++ = (i >> 8) & 0xff;
11053         if (properties) {
11054                 MonoObject *prop;
11055                 for (i = 0; i < mono_array_length (properties); ++i) {
11056                         MonoType *ptype;
11057                         char *pname;
11058
11059                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11060                         get_prop_name_and_type (prop, &pname, &ptype);
11061                         *p++ = 0x54; /* PROPERTY signature */
11062                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11063                         g_free (pname);
11064                 }
11065         }
11066
11067         if (fields) {
11068                 MonoObject *field;
11069                 for (i = 0; i < mono_array_length (fields); ++i) {
11070                         MonoType *ftype;
11071                         char *fname;
11072
11073                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11074                         get_field_name_and_type (field, &fname, &ftype);
11075                         *p++ = 0x53; /* FIELD signature */
11076                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11077                         g_free (fname);
11078                 }
11079         }
11080
11081         g_assert (p - buffer <= buflen);
11082         buflen = p - buffer;
11083         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11084         p = mono_array_addr (result, char, 0);
11085         memcpy (p, buffer, buflen);
11086         g_free (buffer);
11087         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11088                 g_free (sig);
11089         return result;
11090 }
11091
11092 /*
11093  * mono_reflection_setup_internal_class:
11094  * @tb: a TypeBuilder object
11095  *
11096  * Creates a MonoClass that represents the TypeBuilder.
11097  * This is a trick that lets us simplify a lot of reflection code
11098  * (and will allow us to support Build and Run assemblies easier).
11099  */
11100 void
11101 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11102 {
11103         MonoError error;
11104         MonoClass *klass, *parent;
11105
11106         RESOLVE_TYPE (tb->parent, &error);
11107         mono_error_raise_exception (&error); /* FIXME don't raise here */
11108
11109         mono_loader_lock ();
11110
11111         if (tb->parent) {
11112                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11113                 if (!is_ok (&error)) {
11114                         mono_loader_unlock ();
11115                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11116                 }
11117                 /* check so we can compile corlib correctly */
11118                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11119                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11120                         parent = parent_type->data.klass;
11121                 } else {
11122                         parent = mono_class_from_mono_type (parent_type);
11123                 }
11124         } else {
11125                 parent = NULL;
11126         }
11127         
11128         /* the type has already being created: it means we just have to change the parent */
11129         if (tb->type.type) {
11130                 klass = mono_class_from_mono_type (tb->type.type);
11131                 klass->parent = NULL;
11132                 /* fool mono_class_setup_parent */
11133                 klass->supertypes = NULL;
11134                 mono_class_setup_parent (klass, parent);
11135                 mono_class_setup_mono_type (klass);
11136                 mono_loader_unlock ();
11137                 return;
11138         }
11139
11140         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11141
11142         klass->image = &tb->module->dynamic_image->image;
11143
11144         klass->inited = 1; /* we lie to the runtime */
11145         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11146         if (!mono_error_ok (&error))
11147                 goto failure;
11148         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11149         if (!mono_error_ok (&error))
11150                 goto failure;
11151         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11152         klass->flags = tb->attrs;
11153         
11154         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11155
11156         klass->element_class = klass;
11157
11158         if (mono_class_get_ref_info (klass) == NULL) {
11159
11160                 mono_class_set_ref_info (klass, tb);
11161
11162                 /* Put into cache so mono_class_get_checked () will find it.
11163                 Skip nested types as those should not be available on the global scope. */
11164                 if (!tb->nesting_type)
11165                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11166
11167                 /*
11168                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11169                 by performing a mono_class_get which does the full resolution.
11170
11171                 Working around this semantics would require us to write a lot of code for no clear advantage.
11172                 */
11173                 mono_image_append_class_to_reflection_info_set (klass);
11174         } else {
11175                 g_assert (mono_class_get_ref_info (klass) == tb);
11176         }
11177
11178         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11179
11180         if (parent != NULL) {
11181                 mono_class_setup_parent (klass, parent);
11182         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11183                 const char *old_n = klass->name;
11184                 /* trick to get relative numbering right when compiling corlib */
11185                 klass->name = "BuildingObject";
11186                 mono_class_setup_parent (klass, mono_defaults.object_class);
11187                 klass->name = old_n;
11188         }
11189
11190         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11191                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11192                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11193                 klass->instance_size = sizeof (MonoObject);
11194                 klass->size_inited = 1;
11195                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11196         }
11197
11198         mono_class_setup_mono_type (klass);
11199
11200         mono_class_setup_supertypes (klass);
11201
11202         /*
11203          * FIXME: handle interfaces.
11204          */
11205
11206         tb->type.type = &klass->byval_arg;
11207
11208         if (tb->nesting_type) {
11209                 g_assert (tb->nesting_type->type);
11210                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11211                 if (!is_ok (&error)) goto failure;
11212                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11213         }
11214
11215         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11216
11217         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11218         
11219         mono_loader_unlock ();
11220         return;
11221
11222 failure:
11223         mono_loader_unlock ();
11224         mono_error_raise_exception (&error);
11225 }
11226
11227 /*
11228  * mono_reflection_setup_generic_class:
11229  * @tb: a TypeBuilder object
11230  *
11231  * Setup the generic class before adding the first generic parameter.
11232  */
11233 void
11234 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11235 {
11236 }
11237
11238 /*
11239  * mono_reflection_create_generic_class:
11240  * @tb: a TypeBuilder object
11241  *
11242  * Creates the generic class after all generic parameters have been added.
11243  */
11244 void
11245 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11246 {
11247         MonoError error;
11248         MonoClass *klass;
11249         int count, i;
11250
11251         klass = mono_class_from_mono_type (tb->type.type);
11252
11253         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11254
11255         if (klass->generic_container || (count == 0))
11256                 return;
11257
11258         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11259
11260         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11261
11262         klass->generic_container->owner.klass = klass;
11263         klass->generic_container->type_argc = count;
11264         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11265
11266         klass->is_generic = 1;
11267
11268         for (i = 0; i < count; i++) {
11269                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11270                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11271                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11272                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11273                 klass->generic_container->type_params [i] = *param;
11274                 /*Make sure we are a diferent type instance */
11275                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11276                 klass->generic_container->type_params [i].info.pklass = NULL;
11277                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11278
11279                 g_assert (klass->generic_container->type_params [i].param.owner);
11280         }
11281
11282         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11283 }
11284
11285 /*
11286  * mono_reflection_create_internal_class:
11287  * @tb: a TypeBuilder object
11288  *
11289  * Actually create the MonoClass that is associated with the TypeBuilder.
11290  */
11291 void
11292 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11293 {
11294         MonoError error;
11295         MonoClass *klass;
11296
11297         klass = mono_class_from_mono_type (tb->type.type);
11298
11299         mono_loader_lock ();
11300         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11301                 MonoReflectionFieldBuilder *fb;
11302                 MonoClass *ec;
11303                 MonoType *enum_basetype;
11304
11305                 g_assert (tb->fields != NULL);
11306                 g_assert (mono_array_length (tb->fields) >= 1);
11307
11308                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11309
11310                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11311                 if (!is_ok (&error)) {
11312                         mono_loader_unlock ();
11313                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11314                 }
11315                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11316                         mono_loader_unlock ();
11317                         return;
11318                 }
11319
11320                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11321                 if (!is_ok (&error)) {
11322                         mono_loader_unlock ();
11323                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11324                 }
11325                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11326                 if (!klass->element_class)
11327                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11328
11329                 /*
11330                  * get the element_class from the current corlib.
11331                  */
11332                 ec = default_class_from_mono_type (enum_basetype);
11333                 klass->instance_size = ec->instance_size;
11334                 klass->size_inited = 1;
11335                 /* 
11336                  * this is almost safe to do with enums and it's needed to be able
11337                  * to create objects of the enum type (for use in SetConstant).
11338                  */
11339                 /* FIXME: Does this mean enums can't have method overrides ? */
11340                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11341         }
11342         mono_loader_unlock ();
11343 }
11344
11345 static MonoMarshalSpec*
11346 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11347                                                                 MonoReflectionMarshal *minfo)
11348 {
11349         MonoError error;
11350         MonoMarshalSpec *res;
11351
11352         res = image_g_new0 (image, MonoMarshalSpec, 1);
11353         res->native = (MonoMarshalNative)minfo->type;
11354
11355         switch (minfo->type) {
11356         case MONO_NATIVE_LPARRAY:
11357                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11358                 if (minfo->has_size) {
11359                         res->data.array_data.param_num = minfo->param_num;
11360                         res->data.array_data.num_elem = minfo->count;
11361                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11362                 }
11363                 else {
11364                         res->data.array_data.param_num = -1;
11365                         res->data.array_data.num_elem = -1;
11366                         res->data.array_data.elem_mult = -1;
11367                 }
11368                 break;
11369
11370         case MONO_NATIVE_BYVALTSTR:
11371         case MONO_NATIVE_BYVALARRAY:
11372                 res->data.array_data.num_elem = minfo->count;
11373                 break;
11374
11375         case MONO_NATIVE_CUSTOM:
11376                 if (minfo->marshaltyperef) {
11377                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11378                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11379                         res->data.custom_data.custom_name =
11380                                 type_get_fully_qualified_name (marshaltyperef);
11381                 }
11382                 if (minfo->mcookie)
11383                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11384                 break;
11385
11386         default:
11387                 break;
11388         }
11389
11390         return res;
11391 }
11392 #endif /* !DISABLE_REFLECTION_EMIT */
11393
11394 MonoReflectionMarshalAsAttribute*
11395 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11396                                                         MonoMarshalSpec *spec, MonoError *error)
11397 {
11398         MonoReflectionType *rt;
11399         MonoReflectionMarshalAsAttribute *minfo;
11400         MonoType *mtype;
11401
11402         mono_error_init (error);
11403         
11404         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11405         if (!minfo)
11406                 return NULL;
11407         minfo->utype = spec->native;
11408
11409         switch (minfo->utype) {
11410         case MONO_NATIVE_LPARRAY:
11411                 minfo->array_subtype = spec->data.array_data.elem_type;
11412                 minfo->size_const = spec->data.array_data.num_elem;
11413                 if (spec->data.array_data.param_num != -1)
11414                         minfo->size_param_index = spec->data.array_data.param_num;
11415                 break;
11416
11417         case MONO_NATIVE_BYVALTSTR:
11418         case MONO_NATIVE_BYVALARRAY:
11419                 minfo->size_const = spec->data.array_data.num_elem;
11420                 break;
11421
11422         case MONO_NATIVE_CUSTOM:
11423                 if (spec->data.custom_data.custom_name) {
11424                         mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11425                         return_val_if_nok  (error, NULL);
11426
11427                         if (mtype) {
11428                                 rt = mono_type_get_object_checked (domain, mtype, error);
11429                                 if (!rt)
11430                                         return NULL;
11431
11432                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11433                         }
11434
11435                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11436                 }
11437                 if (spec->data.custom_data.cookie)
11438                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11439                 break;
11440
11441         default:
11442                 break;
11443         }
11444
11445         return minfo;
11446 }
11447
11448 #ifndef DISABLE_REFLECTION_EMIT
11449 static MonoMethod*
11450 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11451                                          ReflectionMethodBuilder *rmb,
11452                                          MonoMethodSignature *sig)
11453 {
11454         MonoError error;
11455         MonoMethod *m;
11456         MonoMethodWrapper *wrapperm;
11457         MonoMarshalSpec **specs;
11458         MonoReflectionMethodAux *method_aux;
11459         MonoImage *image;
11460         gboolean dynamic;
11461         int i;
11462
11463         mono_error_init (&error);
11464         /*
11465          * Methods created using a MethodBuilder should have their memory allocated
11466          * inside the image mempool, while dynamic methods should have their memory
11467          * malloc'd.
11468          */
11469         dynamic = rmb->refs != NULL;
11470         image = dynamic ? NULL : klass->image;
11471
11472         if (!dynamic)
11473                 g_assert (!klass->generic_class);
11474
11475         mono_loader_lock ();
11476
11477         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11478                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11479                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11480         else
11481                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11482
11483         wrapperm = (MonoMethodWrapper*)m;
11484
11485         m->dynamic = dynamic;
11486         m->slot = -1;
11487         m->flags = rmb->attrs;
11488         m->iflags = rmb->iattrs;
11489         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11490         m->klass = klass;
11491         m->signature = sig;
11492         m->sre_method = TRUE;
11493         m->skip_visibility = rmb->skip_visibility;
11494         if (rmb->table_idx)
11495                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11496
11497         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11498                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11499                         m->string_ctor = 1;
11500
11501                 m->signature->pinvoke = 1;
11502         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11503                 m->signature->pinvoke = 1;
11504
11505                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11506
11507                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11508                 g_assert (mono_error_ok (&error));
11509                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11510                 g_assert (mono_error_ok (&error));
11511                 
11512                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11513
11514                 if (image_is_dynamic (klass->image))
11515                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11516
11517                 mono_loader_unlock ();
11518
11519                 return m;
11520         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11521                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11522                 MonoMethodHeader *header;
11523                 guint32 code_size;
11524                 gint32 max_stack, i;
11525                 gint32 num_locals = 0;
11526                 gint32 num_clauses = 0;
11527                 guint8 *code;
11528
11529                 if (rmb->ilgen) {
11530                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11531                         code_size = rmb->ilgen->code_len;
11532                         max_stack = rmb->ilgen->max_stack;
11533                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11534                         if (rmb->ilgen->ex_handlers)
11535                                 num_clauses = method_count_clauses (rmb->ilgen);
11536                 } else {
11537                         if (rmb->code) {
11538                                 code = mono_array_addr (rmb->code, guint8, 0);
11539                                 code_size = mono_array_length (rmb->code);
11540                                 /* we probably need to run a verifier on the code... */
11541                                 max_stack = 8; 
11542                         }
11543                         else {
11544                                 code = NULL;
11545                                 code_size = 0;
11546                                 max_stack = 8;
11547                         }
11548                 }
11549
11550                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11551                 header->code_size = code_size;
11552                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11553                 memcpy ((char*)header->code, code, code_size);
11554                 header->max_stack = max_stack;
11555                 header->init_locals = rmb->init_locals;
11556                 header->num_locals = num_locals;
11557
11558                 for (i = 0; i < num_locals; ++i) {
11559                         MonoReflectionLocalBuilder *lb = 
11560                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11561
11562                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11563                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11564                         mono_error_assert_ok (&error);
11565                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11566                 }
11567
11568                 header->num_clauses = num_clauses;
11569                 if (num_clauses) {
11570                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11571                                  rmb->ilgen, num_clauses);
11572                 }
11573
11574                 wrapperm->header = header;
11575         }
11576
11577         if (rmb->generic_params) {
11578                 int count = mono_array_length (rmb->generic_params);
11579                 MonoGenericContainer *container = rmb->generic_container;
11580
11581                 g_assert (container);
11582
11583                 container->type_argc = count;
11584                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11585                 container->owner.method = m;
11586                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11587
11588                 m->is_generic = TRUE;
11589                 mono_method_set_generic_container (m, container);
11590
11591                 for (i = 0; i < count; i++) {
11592                         MonoReflectionGenericParam *gp =
11593                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11594                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11595                         mono_error_assert_ok (&error);
11596                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11597                         container->type_params [i] = *param;
11598                 }
11599
11600                 /*
11601                  * The method signature might have pointers to generic parameters that belong to other methods.
11602                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11603                  * generic parameters.
11604                  */
11605                 for (i = 0; i < m->signature->param_count; ++i) {
11606                         MonoType *t = m->signature->params [i];
11607                         if (t->type == MONO_TYPE_MVAR) {
11608                                 MonoGenericParam *gparam =  t->data.generic_param;
11609                                 if (gparam->num < count) {
11610                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11611                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11612                                 }
11613
11614                         }
11615                 }
11616
11617                 if (klass->generic_container) {
11618                         container->parent = klass->generic_container;
11619                         container->context.class_inst = klass->generic_container->context.class_inst;
11620                 }
11621                 container->context.method_inst = mono_get_shared_generic_inst (container);
11622         }
11623
11624         if (rmb->refs) {
11625                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11626                 int i;
11627                 void **data;
11628
11629                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11630
11631                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11632                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11633                 for (i = 0; i < rmb->nrefs; ++i)
11634                         data [i + 1] = rmb->refs [i];
11635         }
11636
11637         method_aux = NULL;
11638
11639         /* Parameter info */
11640         if (rmb->pinfo) {
11641                 if (!method_aux)
11642                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11643                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11644                 for (i = 0; i <= m->signature->param_count; ++i) {
11645                         MonoReflectionParamBuilder *pb;
11646                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11647                                 if ((i > 0) && (pb->attrs)) {
11648                                         /* Make a copy since it might point to a shared type structure */
11649                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11650                                         m->signature->params [i - 1]->attrs = pb->attrs;
11651                                 }
11652
11653                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11654                                         MonoDynamicImage *assembly;
11655                                         guint32 idx, len;
11656                                         MonoTypeEnum def_type;
11657                                         char *p;
11658                                         const char *p2;
11659
11660                                         if (!method_aux->param_defaults) {
11661                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11662                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11663                                         }
11664                                         assembly = (MonoDynamicImage*)klass->image;
11665                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11666                                         /* Copy the data from the blob since it might get realloc-ed */
11667                                         p = assembly->blob.data + idx;
11668                                         len = mono_metadata_decode_blob_size (p, &p2);
11669                                         len += p2 - p;
11670                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11671                                         method_aux->param_default_types [i] = def_type;
11672                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11673                                 }
11674
11675                                 if (pb->name) {
11676                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11677                                         g_assert (mono_error_ok (&error));
11678                                 }
11679                                 if (pb->cattrs) {
11680                                         if (!method_aux->param_cattr)
11681                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11682                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11683                                 }
11684                         }
11685                 }
11686         }
11687
11688         /* Parameter marshalling */
11689         specs = NULL;
11690         if (rmb->pinfo)         
11691                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11692                         MonoReflectionParamBuilder *pb;
11693                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11694                                 if (pb->marshal_info) {
11695                                         if (specs == NULL)
11696                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11697                                         specs [pb->position] = 
11698                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11699                                 }
11700                         }
11701                 }
11702         if (specs != NULL) {
11703                 if (!method_aux)
11704                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11705                 method_aux->param_marshall = specs;
11706         }
11707
11708         if (image_is_dynamic (klass->image) && method_aux)
11709                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11710
11711         mono_loader_unlock ();
11712
11713         return m;
11714 }       
11715
11716 static MonoMethod*
11717 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11718 {
11719         ReflectionMethodBuilder rmb;
11720         MonoMethodSignature *sig;
11721
11722         mono_loader_lock ();
11723         sig = ctor_builder_to_signature (klass->image, mb);
11724         mono_loader_unlock ();
11725
11726         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11727                 return NULL;
11728
11729         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11730         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11731
11732         /* If we are in a generic class, we might be called multiple times from inflate_method */
11733         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11734                 /* ilgen is no longer needed */
11735                 mb->ilgen = NULL;
11736         }
11737
11738         return mb->mhandle;
11739 }
11740
11741 static MonoMethod*
11742 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11743 {
11744         ReflectionMethodBuilder rmb;
11745         MonoMethodSignature *sig;
11746
11747         mono_error_init (error);
11748
11749         mono_loader_lock ();
11750         sig = method_builder_to_signature (klass->image, mb);
11751         mono_loader_unlock ();
11752
11753         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11754                 return NULL;
11755
11756         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11757         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11758
11759         /* If we are in a generic class, we might be called multiple times from inflate_method */
11760         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11761                 /* ilgen is no longer needed */
11762                 mb->ilgen = NULL;
11763         }
11764         return mb->mhandle;
11765 }
11766
11767 static MonoClassField*
11768 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11769 {
11770         MonoClassField *field;
11771         MonoType *custom;
11772         MonoError error;
11773
11774         field = g_new0 (MonoClassField, 1);
11775
11776         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11777         g_assert (mono_error_ok (&error));
11778         if (fb->attrs || fb->modreq || fb->modopt) {
11779                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11780                 if (!is_ok (&error)) {
11781                         g_free (field);
11782                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11783                 }
11784                 field->type = mono_metadata_type_dup (NULL, type);
11785                 field->type->attrs = fb->attrs;
11786
11787                 g_assert (image_is_dynamic (klass->image));
11788                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11789                 g_free (field->type);
11790                 field->type = mono_metadata_type_dup (klass->image, custom);
11791                 g_free (custom);
11792         } else {
11793                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11794                 if (!is_ok (&error)) {
11795                         g_free (field);
11796                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11797                 }
11798         }
11799         if (fb->offset != -1)
11800                 field->offset = fb->offset;
11801         field->parent = klass;
11802         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11803
11804         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11805
11806         return field;
11807 }
11808 #endif
11809
11810 MonoType*
11811 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11812 {
11813         MonoError error;
11814         MonoClass *klass;
11815         MonoReflectionTypeBuilder *tb = NULL;
11816         gboolean is_dynamic = FALSE;
11817         MonoClass *geninst;
11818
11819         mono_loader_lock ();
11820
11821         if (is_sre_type_builder (mono_object_class (type))) {
11822                 tb = (MonoReflectionTypeBuilder *) type;
11823
11824                 is_dynamic = TRUE;
11825         } else if (is_sre_generic_instance (mono_object_class (type))) {
11826                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11827                 MonoReflectionType *gtd = rgi->generic_type;
11828
11829                 if (is_sre_type_builder (mono_object_class (gtd))) {
11830                         tb = (MonoReflectionTypeBuilder *)gtd;
11831                         is_dynamic = TRUE;
11832                 }
11833         }
11834
11835         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11836         if (tb && tb->generic_container)
11837                 mono_reflection_create_generic_class (tb);
11838
11839         MonoType *t = mono_reflection_type_get_handle (type, &error);
11840         mono_error_raise_exception (&error); /* FIXME don't raise here */
11841
11842         klass = mono_class_from_mono_type (t);
11843         if (!klass->generic_container) {
11844                 mono_loader_unlock ();
11845                 return NULL;
11846         }
11847
11848         if (klass->wastypebuilder) {
11849                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11850
11851                 is_dynamic = TRUE;
11852         }
11853
11854         mono_loader_unlock ();
11855
11856         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11857
11858         return &geninst->byval_arg;
11859 }
11860
11861 MonoClass*
11862 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11863 {
11864         MonoGenericClass *gclass;
11865         MonoGenericInst *inst;
11866
11867         g_assert (klass->generic_container);
11868
11869         inst = mono_metadata_get_generic_inst (type_argc, types);
11870         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11871
11872         return mono_generic_class_get_class (gclass);
11873 }
11874
11875 MonoReflectionMethod*
11876 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11877 {
11878         MonoError error;
11879         MonoClass *klass;
11880         MonoMethod *method, *inflated;
11881         MonoMethodInflated *imethod;
11882         MonoGenericContext tmp_context;
11883         MonoGenericInst *ginst;
11884         MonoType **type_argv;
11885         int count, i;
11886
11887         /*FIXME but this no longer should happen*/
11888         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11889 #ifndef DISABLE_REFLECTION_EMIT
11890                 MonoReflectionMethodBuilder *mb = NULL;
11891                 MonoType *tb;
11892                 MonoClass *klass;
11893
11894                 mb = (MonoReflectionMethodBuilder *) rmethod;
11895                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11896                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11897                 klass = mono_class_from_mono_type (tb);
11898
11899                 method = methodbuilder_to_mono_method (klass, mb, &error);
11900                 if (!method)
11901                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11902 #else
11903                 g_assert_not_reached ();
11904                 method = NULL;
11905 #endif
11906         } else {
11907                 method = rmethod->method;
11908         }
11909
11910         klass = method->klass;
11911
11912         if (method->is_inflated)
11913                 method = ((MonoMethodInflated *) method)->declaring;
11914
11915         count = mono_method_signature (method)->generic_param_count;
11916         if (count != mono_array_length (types))
11917                 return NULL;
11918
11919         type_argv = g_new0 (MonoType *, count);
11920         for (i = 0; i < count; i++) {
11921                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11922                 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
11923                 if (!is_ok (&error)) {
11924                         g_free (type_argv);
11925                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11926                 }
11927         }
11928         ginst = mono_metadata_get_generic_inst (count, type_argv);
11929         g_free (type_argv);
11930
11931         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11932         tmp_context.method_inst = ginst;
11933
11934         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11935         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11936         imethod = (MonoMethodInflated *) inflated;
11937
11938         /*FIXME but I think this is no longer necessary*/
11939         if (image_is_dynamic (method->klass->image)) {
11940                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11941                 /*
11942                  * This table maps metadata structures representing inflated methods/fields
11943                  * to the reflection objects representing their generic definitions.
11944                  */
11945                 mono_image_lock ((MonoImage*)image);
11946                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11947                 mono_image_unlock ((MonoImage*)image);
11948         }
11949
11950         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11951                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11952         
11953         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11954         mono_error_raise_exception (&error); /* FIXME don't raise here */
11955         return ret;
11956 }
11957
11958 #ifndef DISABLE_REFLECTION_EMIT
11959
11960 static MonoMethod *
11961 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11962 {
11963         MonoMethodInflated *imethod;
11964         MonoGenericContext *context;
11965         int i;
11966
11967         /*
11968          * With generic code sharing the klass might not be inflated.
11969          * This can happen because classes inflated with their own
11970          * type arguments are "normalized" to the uninflated class.
11971          */
11972         if (!klass->generic_class)
11973                 return method;
11974
11975         context = mono_class_get_context (klass);
11976
11977         if (klass->method.count && klass->methods) {
11978                 /* Find the already created inflated method */
11979                 for (i = 0; i < klass->method.count; ++i) {
11980                         g_assert (klass->methods [i]->is_inflated);
11981                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11982                                 break;
11983                 }
11984                 g_assert (i < klass->method.count);
11985                 imethod = (MonoMethodInflated*)klass->methods [i];
11986         } else {
11987                 MonoError error;
11988                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11989                 mono_error_assert_ok (&error);
11990         }
11991
11992         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11993                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11994
11995                 mono_image_lock ((MonoImage*)image);
11996                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11997                 mono_image_unlock ((MonoImage*)image);
11998         }
11999         return (MonoMethod *) imethod;
12000 }
12001
12002 static MonoMethod *
12003 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12004 {
12005         MonoMethod *method;
12006         MonoClass *gklass;
12007
12008         mono_error_init (error);
12009
12010         MonoClass *type_class = mono_object_class (type);
12011
12012         if (is_sre_generic_instance (type_class)) {
12013                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12014                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12015                 return_val_if_nok (error, NULL);
12016                 gklass = mono_class_from_mono_type (generic_type);
12017         } else if (is_sre_type_builder (type_class)) {
12018                 MonoType *t = mono_reflection_type_get_handle (type, error);
12019                 return_val_if_nok (error, NULL);
12020                 gklass = mono_class_from_mono_type (t);
12021         } else if (type->type) {
12022                 gklass = mono_class_from_mono_type (type->type);
12023                 gklass = mono_class_get_generic_type_definition (gklass);
12024         } else {
12025                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12026         }
12027
12028         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12029                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12030                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12031                 else {
12032                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12033                         if (!method)
12034                                 return NULL;
12035                 }
12036         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12037                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12038                 if (!method)
12039                         return NULL;
12040         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12041                 method = ((MonoReflectionMethod *) obj)->method;
12042         else {
12043                 method = NULL; /* prevent compiler warning */
12044                 g_error ("can't handle type %s", obj->vtable->klass->name);
12045         }
12046
12047         MonoType *t = mono_reflection_type_get_handle (type, error);
12048         return_val_if_nok (error, NULL);
12049         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12050 }
12051
12052 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12053 void
12054 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12055 {
12056         MonoError error;
12057         MonoGenericClass *gclass;
12058         MonoDynamicGenericClass *dgclass;
12059         MonoClass *klass, *gklass;
12060         MonoType *gtype;
12061         int i;
12062
12063         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12064         mono_error_raise_exception (&error); /* FIXME don't raise here */
12065         klass = mono_class_from_mono_type (gtype);
12066         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12067         gclass = gtype->data.generic_class;
12068
12069         if (!gclass->is_dynamic)
12070                 return;
12071
12072         dgclass = (MonoDynamicGenericClass *) gclass;
12073
12074         if (dgclass->initialized)
12075                 return;
12076
12077         gklass = gclass->container_class;
12078         mono_class_init (gklass);
12079
12080         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12081
12082         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12083         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12084         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12085
12086         for (i = 0; i < dgclass->count_fields; i++) {
12087                 MonoError error;
12088                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12089                 MonoClassField *field, *inflated_field = NULL;
12090
12091                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12092                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12093                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12094                         field = ((MonoReflectionField *) obj)->field;
12095                 else {
12096                         field = NULL; /* prevent compiler warning */
12097                         g_assert_not_reached ();
12098                 }
12099
12100                 dgclass->fields [i] = *field;
12101                 dgclass->fields [i].parent = klass;
12102                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12103                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12104                 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12105                 dgclass->field_generic_types [i] = field->type;
12106                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12107                 dgclass->field_objects [i] = obj;
12108
12109                 if (inflated_field) {
12110                         g_free (inflated_field);
12111                 } else {
12112                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12113                 }
12114         }
12115
12116         dgclass->initialized = TRUE;
12117 }
12118
12119 void
12120 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12121 {
12122         MonoDynamicGenericClass *dgclass;
12123         int i;
12124
12125         g_assert (gclass->is_dynamic);
12126
12127         dgclass = (MonoDynamicGenericClass *)gclass;
12128
12129         for (i = 0; i < dgclass->count_fields; ++i) {
12130                 MonoClassField *field = dgclass->fields + i;
12131                 mono_metadata_free_type (field->type);
12132                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12133         }
12134 }
12135
12136 static void
12137 fix_partial_generic_class (MonoClass *klass)
12138 {
12139         MonoClass *gklass = klass->generic_class->container_class;
12140         MonoDynamicGenericClass *dgclass;
12141         int i;
12142
12143         if (klass->wastypebuilder)
12144                 return;
12145
12146         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12147         if (klass->parent != gklass->parent) {
12148                 MonoError error;
12149                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12150                 if (mono_error_ok (&error)) {
12151                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12152                         mono_metadata_free_type (parent_type);
12153                         if (parent != klass->parent) {
12154                                 /*fool mono_class_setup_parent*/
12155                                 klass->supertypes = NULL;
12156                                 mono_class_setup_parent (klass, parent);
12157                         }
12158                 } else {
12159                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12160                         mono_error_cleanup (&error);
12161                         if (gklass->wastypebuilder)
12162                                 klass->wastypebuilder = TRUE;
12163                         return;
12164                 }
12165         }
12166
12167         if (!dgclass->initialized)
12168                 return;
12169
12170         if (klass->method.count != gklass->method.count) {
12171                 klass->method.count = gklass->method.count;
12172                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12173
12174                 for (i = 0; i < klass->method.count; i++) {
12175                         MonoError error;
12176                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12177                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12178                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12179                 }
12180         }
12181
12182         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12183                 klass->interface_count = gklass->interface_count;
12184                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12185                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12186
12187                 for (i = 0; i < gklass->interface_count; ++i) {
12188                         MonoError error;
12189                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12190                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12191
12192                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12193                         mono_metadata_free_type (iface_type);
12194
12195                         ensure_runtime_vtable (klass->interfaces [i], &error);
12196                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12197                 }
12198                 klass->interfaces_inited = 1;
12199         }
12200
12201         if (klass->field.count != gklass->field.count) {
12202                 klass->field.count = gklass->field.count;
12203                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12204
12205                 for (i = 0; i < klass->field.count; i++) {
12206                         MonoError error;
12207                         klass->fields [i] = gklass->fields [i];
12208                         klass->fields [i].parent = klass;
12209                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12210                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12211                 }
12212         }
12213
12214         /*We can only finish with this klass once it's parent has as well*/
12215         if (gklass->wastypebuilder)
12216                 klass->wastypebuilder = TRUE;
12217         return;
12218 }
12219
12220 /**
12221  * ensure_generic_class_runtime_vtable:
12222  * @klass a generic class
12223  * @error set on error
12224  *
12225  * Ensures that the generic container of @klass has a vtable and
12226  * returns TRUE on success.  On error returns FALSE and sets @error.
12227  */
12228 static gboolean
12229 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12230 {
12231         MonoClass *gklass = klass->generic_class->container_class;
12232
12233         mono_error_init (error);
12234
12235         if (!ensure_runtime_vtable (gklass, error))
12236                 return FALSE;
12237
12238         fix_partial_generic_class (klass);
12239
12240         return TRUE;
12241 }
12242
12243 /**
12244  * ensure_runtime_vtable:
12245  * @klass the class
12246  * @error set on error
12247  *
12248  * Ensures that @klass has a vtable and returns TRUE on success. On
12249  * error returns FALSE and sets @error.
12250  */
12251 static gboolean
12252 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12253 {
12254         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12255         int i, num, j;
12256
12257         mono_error_init (error);
12258
12259         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12260                 return TRUE;
12261         if (klass->parent)
12262                 if (!ensure_runtime_vtable (klass->parent, error))
12263                         return FALSE;
12264
12265         if (tb) {
12266                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12267                 num += tb->num_methods;
12268                 klass->method.count = num;
12269                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12270                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12271                 for (i = 0; i < num; ++i) {
12272                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12273                         if (!ctor)
12274                                 return FALSE;
12275                         klass->methods [i] = ctor;
12276                 }
12277                 num = tb->num_methods;
12278                 j = i;
12279                 for (i = 0; i < num; ++i) {
12280                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12281                         if (!meth)
12282                                 return FALSE;
12283                         klass->methods [j++] = meth;
12284                 }
12285         
12286                 if (tb->interfaces) {
12287                         klass->interface_count = mono_array_length (tb->interfaces);
12288                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12289                         for (i = 0; i < klass->interface_count; ++i) {
12290                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12291                                 return_val_if_nok (error, FALSE);
12292                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12293                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12294                                         return FALSE;
12295                         }
12296                         klass->interfaces_inited = 1;
12297                 }
12298         } else if (klass->generic_class){
12299                 if (!ensure_generic_class_runtime_vtable (klass, error))
12300                         return FALSE;
12301         }
12302
12303         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12304                 int slot_num = 0;
12305                 for (i = 0; i < klass->method.count; ++i) {
12306                         MonoMethod *im = klass->methods [i];
12307                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12308                                 im->slot = slot_num++;
12309                 }
12310                 
12311                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12312                 mono_class_setup_interface_offsets (klass);
12313                 mono_class_setup_interface_id (klass);
12314         }
12315
12316         /*
12317          * The generic vtable is needed even if image->run is not set since some
12318          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12319          * method->slot being defined.
12320          */
12321
12322         /* 
12323          * tb->methods could not be freed since it is used for determining 
12324          * overrides during dynamic vtable construction.
12325          */
12326
12327         return TRUE;
12328 }
12329
12330 static MonoMethod*
12331 mono_reflection_method_get_handle (MonoObject *method)
12332 {
12333         MonoError error;
12334         MonoClass *klass = mono_object_class (method);
12335         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12336                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12337                 return sr_method->method;
12338         }
12339         if (is_sre_method_builder (klass)) {
12340                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12341                 return mb->mhandle;
12342         }
12343         if (is_sre_method_on_tb_inst (klass)) {
12344                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12345                 MonoMethod *result;
12346                 /*FIXME move this to a proper method and unify with resolve_object*/
12347                 if (m->method_args) {
12348                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12349                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12350                 } else {
12351                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12352                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12353                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12354                         MonoMethod *mono_method;
12355
12356                         if (is_sre_method_builder (mono_object_class (m->mb)))
12357                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12358                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12359                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12360                         else
12361                                 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)));
12362
12363                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12364                 }
12365                 return result;
12366         }
12367
12368         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12369         return NULL;
12370 }
12371
12372 void
12373 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12374 {
12375         MonoReflectionTypeBuilder *tb;
12376         int i, j, onum;
12377         MonoReflectionMethod *m;
12378
12379         *overrides = NULL;
12380         *num_overrides = 0;
12381
12382         g_assert (image_is_dynamic (klass->image));
12383
12384         if (!mono_class_get_ref_info (klass))
12385                 return;
12386
12387         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12388
12389         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12390
12391         onum = 0;
12392         if (tb->methods) {
12393                 for (i = 0; i < tb->num_methods; ++i) {
12394                         MonoReflectionMethodBuilder *mb = 
12395                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12396                         if (mb->override_methods)
12397                                 onum += mono_array_length (mb->override_methods);
12398                 }
12399         }
12400
12401         if (onum) {
12402                 *overrides = g_new0 (MonoMethod*, onum * 2);
12403
12404                 onum = 0;
12405                 for (i = 0; i < tb->num_methods; ++i) {
12406                         MonoReflectionMethodBuilder *mb = 
12407                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12408                         if (mb->override_methods) {
12409                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12410                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12411
12412                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12413                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12414
12415                                         g_assert (mb->mhandle);
12416
12417                                         onum ++;
12418                                 }
12419                         }
12420                 }
12421         }
12422
12423         *num_overrides = onum;
12424 }
12425
12426 static void
12427 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12428 {
12429         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12430         MonoReflectionFieldBuilder *fb;
12431         MonoClassField *field;
12432         MonoImage *image = klass->image;
12433         const char *p, *p2;
12434         int i;
12435         guint32 len, idx, real_size = 0;
12436
12437         klass->field.count = tb->num_fields;
12438         klass->field.first = 0;
12439
12440         mono_error_init (error);
12441
12442         if (tb->class_size) {
12443                 if ((tb->packing_size & 0xffffff00) != 0) {
12444                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12445                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12446                         return;
12447                 }
12448                 klass->packing_size = tb->packing_size;
12449                 real_size = klass->instance_size + tb->class_size;
12450         }
12451
12452         if (!klass->field.count) {
12453                 klass->instance_size = MAX (klass->instance_size, real_size);
12454                 return;
12455         }
12456         
12457         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12458         mono_class_alloc_ext (klass);
12459         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12460         /*
12461         This is, guess what, a hack.
12462         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12463         On the static path no field class is resolved, only types are built. This is the right thing to do
12464         but we suck.
12465         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12466         */
12467         klass->size_inited = 1;
12468
12469         for (i = 0; i < klass->field.count; ++i) {
12470                 MonoArray *rva_data;
12471                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12472                 field = &klass->fields [i];
12473                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12474                 if (!mono_error_ok (error))
12475                         return;
12476                 if (fb->attrs) {
12477                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12478                         return_if_nok (error);
12479                         field->type = mono_metadata_type_dup (klass->image, type);
12480                         field->type->attrs = fb->attrs;
12481                 } else {
12482                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12483                         return_if_nok (error);
12484                 }
12485
12486                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12487                         char *base = mono_array_addr (rva_data, char, 0);
12488                         size_t size = mono_array_length (rva_data);
12489                         char *data = (char *)mono_image_alloc (klass->image, size);
12490                         memcpy (data, base, size);
12491                         klass->ext->field_def_values [i].data = data;
12492                 }
12493                 if (fb->offset != -1)
12494                         field->offset = fb->offset;
12495                 field->parent = klass;
12496                 fb->handle = field;
12497                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12498
12499                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12500                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12501                 }
12502                 if (fb->def_value) {
12503                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12504                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12505                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12506                         /* Copy the data from the blob since it might get realloc-ed */
12507                         p = assembly->blob.data + idx;
12508                         len = mono_metadata_decode_blob_size (p, &p2);
12509                         len += p2 - p;
12510                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12511                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12512                 }
12513         }
12514
12515         klass->instance_size = MAX (klass->instance_size, real_size);
12516         mono_class_layout_fields (klass);
12517 }
12518
12519 static void
12520 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12521 {
12522         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12523         MonoReflectionPropertyBuilder *pb;
12524         MonoImage *image = klass->image;
12525         MonoProperty *properties;
12526         int i;
12527
12528         mono_error_init (error);
12529
12530         if (!klass->ext)
12531                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12532
12533         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12534         klass->ext->property.first = 0;
12535
12536         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12537         klass->ext->properties = properties;
12538         for (i = 0; i < klass->ext->property.count; ++i) {
12539                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12540                 properties [i].parent = klass;
12541                 properties [i].attrs = pb->attrs;
12542                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12543                 if (!mono_error_ok (error))
12544                         return;
12545                 if (pb->get_method)
12546                         properties [i].get = pb->get_method->mhandle;
12547                 if (pb->set_method)
12548                         properties [i].set = pb->set_method->mhandle;
12549
12550                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12551                 if (pb->def_value) {
12552                         guint32 len, idx;
12553                         const char *p, *p2;
12554                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12555                         if (!klass->ext->prop_def_values)
12556                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12557                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12558                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12559                         /* Copy the data from the blob since it might get realloc-ed */
12560                         p = assembly->blob.data + idx;
12561                         len = mono_metadata_decode_blob_size (p, &p2);
12562                         len += p2 - p;
12563                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12564                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12565                 }
12566         }
12567 }
12568
12569 MonoReflectionEvent *
12570 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12571 {
12572         MonoError error;
12573         MonoEvent *event = g_new0 (MonoEvent, 1);
12574         MonoClass *klass;
12575
12576         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12577         mono_error_raise_exception (&error); /* FIXME don't raise here */
12578         klass = mono_class_from_mono_type (type);
12579
12580         event->parent = klass;
12581         event->attrs = eb->attrs;
12582         event->name = mono_string_to_utf8 (eb->name);
12583         if (eb->add_method)
12584                 event->add = eb->add_method->mhandle;
12585         if (eb->remove_method)
12586                 event->remove = eb->remove_method->mhandle;
12587         if (eb->raise_method)
12588                 event->raise = eb->raise_method->mhandle;
12589
12590 #ifndef MONO_SMALL_CONFIG
12591         if (eb->other_methods) {
12592                 int j;
12593                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12594                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12595                         MonoReflectionMethodBuilder *mb = 
12596                                 mono_array_get (eb->other_methods,
12597                                                 MonoReflectionMethodBuilder*, j);
12598                         event->other [j] = mb->mhandle;
12599                 }
12600         }
12601 #endif
12602
12603         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12604         mono_error_raise_exception (&error); /* FIXME don't raise here */
12605         return ev_obj;
12606 }
12607
12608 static void
12609 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12610 {
12611         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12612         MonoReflectionEventBuilder *eb;
12613         MonoImage *image = klass->image;
12614         MonoEvent *events;
12615         int i;
12616
12617         mono_error_init (error);
12618
12619         if (!klass->ext)
12620                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12621
12622         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12623         klass->ext->event.first = 0;
12624
12625         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12626         klass->ext->events = events;
12627         for (i = 0; i < klass->ext->event.count; ++i) {
12628                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12629                 events [i].parent = klass;
12630                 events [i].attrs = eb->attrs;
12631                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12632                 if (!mono_error_ok (error))
12633                         return;
12634                 if (eb->add_method)
12635                         events [i].add = eb->add_method->mhandle;
12636                 if (eb->remove_method)
12637                         events [i].remove = eb->remove_method->mhandle;
12638                 if (eb->raise_method)
12639                         events [i].raise = eb->raise_method->mhandle;
12640
12641 #ifndef MONO_SMALL_CONFIG
12642                 if (eb->other_methods) {
12643                         int j;
12644                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12645                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12646                                 MonoReflectionMethodBuilder *mb = 
12647                                         mono_array_get (eb->other_methods,
12648                                                                         MonoReflectionMethodBuilder*, j);
12649                                 events [i].other [j] = mb->mhandle;
12650                         }
12651                 }
12652 #endif
12653                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12654         }
12655 }
12656
12657 static gboolean
12658 remove_instantiations_of_and_ensure_contents (gpointer key,
12659                                                   gpointer value,
12660                                                   gpointer user_data)
12661 {
12662         MonoType *type = (MonoType*)key;
12663         MonoClass *klass = (MonoClass*)user_data;
12664
12665         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12666                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12667                 return TRUE;
12668         } else
12669                 return FALSE;
12670 }
12671
12672 static void
12673 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12674 {
12675         mono_error_init (error);
12676         int i;
12677
12678         if (!arr)
12679                 return;
12680
12681         for (i = 0; i < mono_array_length (arr); ++i) {
12682                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12683                 if (!mono_error_ok (error))
12684                         break;
12685         }
12686 }
12687
12688 MonoReflectionType*
12689 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12690 {
12691         MonoError error;
12692         MonoClass *klass;
12693         MonoDomain* domain;
12694         MonoReflectionType* res;
12695         int i, j;
12696
12697         domain = mono_object_domain (tb);
12698         klass = mono_class_from_mono_type (tb->type.type);
12699
12700         /*
12701          * Check for user defined Type subclasses.
12702          */
12703         RESOLVE_TYPE (tb->parent, &error);
12704         mono_error_raise_exception (&error); /* FIXME don't raise here */
12705         check_array_for_usertypes (tb->interfaces, &error);
12706         mono_error_raise_exception (&error); /*FIXME don't raise here */
12707         if (tb->fields) {
12708                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12709                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12710                         if (fb) {
12711                                 RESOLVE_TYPE (fb->type, &error);
12712                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12713                                 check_array_for_usertypes (fb->modreq, &error);
12714                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12715                                 check_array_for_usertypes (fb->modopt, &error);
12716                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12717                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12718                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12719                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12720                                 }
12721                         }
12722                 }
12723         }
12724         if (tb->methods) {
12725                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12726                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12727                         if (mb) {
12728                                 RESOLVE_TYPE (mb->rtype, &error);
12729                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12730                                 check_array_for_usertypes (mb->return_modreq, &error);
12731                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12732                                 check_array_for_usertypes (mb->return_modopt, &error);
12733                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12734                                 check_array_for_usertypes (mb->parameters, &error);
12735                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12736                                 if (mb->param_modreq)
12737                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12738                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12739                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12740                                         }
12741                                 if (mb->param_modopt)
12742                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12743                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12744                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12745                                         }
12746                         }
12747                 }
12748         }
12749         if (tb->ctors) {
12750                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12751                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12752                         if (mb) {
12753                                 check_array_for_usertypes (mb->parameters, &error);
12754                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12755                                 if (mb->param_modreq)
12756                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12757                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12758                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12759                                         }
12760                                 if (mb->param_modopt)
12761                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12762                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12763                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12764                                         }
12765                         }
12766                 }
12767         }
12768
12769         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12770
12771         /* 
12772          * we need to lock the domain because the lock will be taken inside
12773          * So, we need to keep the locking order correct.
12774          */
12775         mono_loader_lock ();
12776         mono_domain_lock (domain);
12777         if (klass->wastypebuilder) {
12778                 mono_domain_unlock (domain);
12779                 mono_loader_unlock ();
12780
12781                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12782                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12783
12784                 return res;
12785         }
12786         /*
12787          * Fields to set in klass:
12788          * the various flags: delegate/unicode/contextbound etc.
12789          */
12790         klass->flags = tb->attrs;
12791         klass->has_cctor = 1;
12792         klass->has_finalize = 1;
12793         klass->has_finalize_inited = 1;
12794
12795         mono_class_setup_parent (klass, klass->parent);
12796         /* fool mono_class_setup_supertypes */
12797         klass->supertypes = NULL;
12798         mono_class_setup_supertypes (klass);
12799         mono_class_setup_mono_type (klass);
12800
12801 #if 0
12802         if (!((MonoDynamicImage*)klass->image)->run) {
12803                 if (klass->generic_container) {
12804                         /* FIXME: The code below can't handle generic classes */
12805                         klass->wastypebuilder = TRUE;
12806                         mono_loader_unlock ();
12807                         mono_domain_unlock (domain);
12808
12809                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12810                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12811
12812                         return res;
12813                 }
12814         }
12815 #endif
12816
12817         /* enums are done right away */
12818         if (!klass->enumtype)
12819                 if (!ensure_runtime_vtable (klass, &error))
12820                         goto failure;
12821
12822         if (tb->subtypes) {
12823                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12824                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12825                         mono_class_alloc_ext (klass);
12826                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12827                         if (!is_ok (&error)) goto failure;
12828                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12829                 }
12830         }
12831
12832         klass->nested_classes_inited = TRUE;
12833
12834         /* fields and object layout */
12835         if (klass->parent) {
12836                 if (!klass->parent->size_inited)
12837                         mono_class_init (klass->parent);
12838                 klass->instance_size = klass->parent->instance_size;
12839                 klass->sizes.class_size = 0;
12840                 klass->min_align = klass->parent->min_align;
12841                 /* if the type has no fields we won't call the field_setup
12842                  * routine which sets up klass->has_references.
12843                  */
12844                 klass->has_references |= klass->parent->has_references;
12845         } else {
12846                 klass->instance_size = sizeof (MonoObject);
12847                 klass->min_align = 1;
12848         }
12849
12850         /* FIXME: handle packing_size and instance_size */
12851         typebuilder_setup_fields (klass, &error);
12852         if (!mono_error_ok (&error))
12853                 goto failure;
12854         typebuilder_setup_properties (klass, &error);
12855         if (!mono_error_ok (&error))
12856                 goto failure;
12857
12858         typebuilder_setup_events (klass, &error);
12859         if (!mono_error_ok (&error))
12860                 goto failure;
12861
12862         klass->wastypebuilder = TRUE;
12863
12864         /* 
12865          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12866          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12867          * we want to return normal System.MonoType objects, so clear these out from the cache.
12868          *
12869          * Together with this we must ensure the contents of all instances to match the created type.
12870          */
12871         if (domain->type_hash && klass->generic_container)
12872                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12873
12874         mono_domain_unlock (domain);
12875         mono_loader_unlock ();
12876
12877         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12878                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12879                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12880         }
12881
12882         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12883         mono_error_raise_exception (&error); /* FIXME don't raise here */
12884
12885         g_assert (res != (MonoReflectionType*)tb);
12886
12887         return res;
12888
12889 failure:
12890         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12891         klass->wastypebuilder = TRUE;
12892         mono_domain_unlock (domain);
12893         mono_loader_unlock ();
12894         mono_error_raise_exception (&error);
12895         return NULL;
12896 }
12897
12898 void
12899 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12900 {
12901         MonoGenericParamFull *param;
12902         MonoImage *image;
12903         MonoClass *pklass;
12904         MonoError error;
12905
12906         image = &gparam->tbuilder->module->dynamic_image->image;
12907
12908         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12909
12910         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12911         g_assert (mono_error_ok (&error));
12912         param->param.num = gparam->index;
12913
12914         if (gparam->mbuilder) {
12915                 if (!gparam->mbuilder->generic_container) {
12916                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
12917                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12918
12919                         MonoClass *klass = mono_class_from_mono_type (tb);
12920                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12921                         gparam->mbuilder->generic_container->is_method = TRUE;
12922                         /* 
12923                          * Cannot set owner.method, since the MonoMethod is not created yet.
12924                          * Set the image field instead, so type_in_image () works.
12925                          */
12926                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12927                         gparam->mbuilder->generic_container->owner.image = klass->image;
12928                 }
12929                 param->param.owner = gparam->mbuilder->generic_container;
12930         } else if (gparam->tbuilder) {
12931                 if (!gparam->tbuilder->generic_container) {
12932                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
12933                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12934                         MonoClass *klass = mono_class_from_mono_type (tb);
12935                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12936                         gparam->tbuilder->generic_container->owner.klass = klass;
12937                 }
12938                 param->param.owner = gparam->tbuilder->generic_container;
12939         }
12940
12941         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12942
12943         gparam->type.type = &pklass->byval_arg;
12944
12945         mono_class_set_ref_info (pklass, gparam);
12946         mono_image_append_class_to_reflection_info_set (pklass);
12947 }
12948
12949 MonoArray *
12950 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12951 {
12952         MonoError error;
12953         MonoReflectionModuleBuilder *module = sig->module;
12954         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12955         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12956         guint32 buflen, i;
12957         MonoArray *result;
12958         SigBuffer buf;
12959
12960         check_array_for_usertypes (sig->arguments, &error);
12961         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12962
12963         sigbuffer_init (&buf, 32);
12964
12965         sigbuffer_add_value (&buf, 0x07);
12966         sigbuffer_add_value (&buf, na);
12967         if (assembly != NULL){
12968                 for (i = 0; i < na; ++i) {
12969                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12970                         encode_reflection_type (assembly, type, &buf);
12971                 }
12972         }
12973
12974         buflen = buf.p - buf.buf;
12975         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12976         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12977         sigbuffer_free (&buf);
12978
12979         return result;
12980 }
12981
12982 MonoArray *
12983 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12984 {
12985         MonoError error;
12986         MonoDynamicImage *assembly = sig->module->dynamic_image;
12987         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12988         guint32 buflen, i;
12989         MonoArray *result;
12990         SigBuffer buf;
12991
12992         check_array_for_usertypes (sig->arguments, &error);
12993         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12994
12995         sigbuffer_init (&buf, 32);
12996
12997         sigbuffer_add_value (&buf, 0x06);
12998         for (i = 0; i < na; ++i) {
12999                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13000                 encode_reflection_type (assembly, type, &buf);
13001         }
13002
13003         buflen = buf.p - buf.buf;
13004         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13005         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13006         sigbuffer_free (&buf);
13007
13008         return result;
13009 }
13010
13011 typedef struct {
13012         MonoMethod *handle;
13013         MonoDomain *domain;
13014 } DynamicMethodReleaseData;
13015
13016 /*
13017  * The runtime automatically clean up those after finalization.
13018 */      
13019 static MonoReferenceQueue *dynamic_method_queue;
13020
13021 static void
13022 free_dynamic_method (void *dynamic_method)
13023 {
13024         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13025         MonoDomain *domain = data->domain;
13026         MonoMethod *method = data->handle;
13027         guint32 dis_link;
13028
13029         mono_domain_lock (domain);
13030         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13031         g_hash_table_remove (domain->method_to_dyn_method, method);
13032         mono_domain_unlock (domain);
13033         g_assert (dis_link);
13034         mono_gchandle_free (dis_link);
13035
13036         mono_runtime_free_method (domain, method);
13037         g_free (data);
13038 }
13039
13040 void 
13041 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13042 {
13043         MonoError error;
13044         MonoReferenceQueue *queue;
13045         MonoMethod *handle;
13046         DynamicMethodReleaseData *release_data;
13047         ReflectionMethodBuilder rmb;
13048         MonoMethodSignature *sig;
13049         MonoClass *klass;
13050         MonoDomain *domain;
13051         GSList *l;
13052         int i;
13053
13054         if (mono_runtime_is_shutting_down ())
13055                 mono_raise_exception (mono_get_exception_invalid_operation (""));
13056
13057         if (!(queue = dynamic_method_queue)) {
13058                 mono_loader_lock ();
13059                 if (!(queue = dynamic_method_queue))
13060                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13061                 mono_loader_unlock ();
13062         }
13063
13064         sig = dynamic_method_to_signature (mb);
13065
13066         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13067
13068         /*
13069          * Resolve references.
13070          */
13071         /* 
13072          * Every second entry in the refs array is reserved for storing handle_class,
13073          * which is needed by the ldtoken implementation in the JIT.
13074          */
13075         rmb.nrefs = mb->nrefs;
13076         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13077         for (i = 0; i < mb->nrefs; i += 2) {
13078                 MonoClass *handle_class;
13079                 gpointer ref;
13080                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13081
13082                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13083                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13084                         /*
13085                          * The referenced DynamicMethod should already be created by the managed
13086                          * code, except in the case of circular references. In that case, we store
13087                          * method in the refs array, and fix it up later when the referenced 
13088                          * DynamicMethod is created.
13089                          */
13090                         if (method->mhandle) {
13091                                 ref = method->mhandle;
13092                         } else {
13093                                 /* FIXME: GC object stored in unmanaged memory */
13094                                 ref = method;
13095
13096                                 /* FIXME: GC object stored in unmanaged memory */
13097                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13098                         }
13099                         handle_class = mono_defaults.methodhandle_class;
13100                 } else {
13101                         MonoException *ex = NULL;
13102                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13103                         if (!ref)
13104                                 ex = mono_get_exception_type_load (NULL, NULL);
13105                         else if (mono_security_core_clr_enabled ())
13106                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13107
13108                         if (ex) {
13109                                 g_free (rmb.refs);
13110                                 mono_raise_exception (ex);
13111                                 return;
13112                         }
13113                 }
13114
13115                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13116                 rmb.refs [i + 1] = handle_class;
13117         }               
13118
13119         if (mb->owner) {
13120                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13121                 if (!is_ok (&error)) {
13122                         g_free (rmb.refs);
13123                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13124                 }
13125                 klass = mono_class_from_mono_type (owner_type);
13126         } else {
13127                 klass = mono_defaults.object_class;
13128         }
13129
13130         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13131         release_data = g_new (DynamicMethodReleaseData, 1);
13132         release_data->handle = handle;
13133         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13134         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13135                 g_free (release_data);
13136
13137         /* Fix up refs entries pointing at us */
13138         for (l = mb->referenced_by; l; l = l->next) {
13139                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13140                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13141                 gpointer *data;
13142                 
13143                 g_assert (method->mhandle);
13144
13145                 data = (gpointer*)wrapper->method_data;
13146                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13147                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13148                                 data [i + 1] = mb->mhandle;
13149                 }
13150         }
13151         g_slist_free (mb->referenced_by);
13152
13153         g_free (rmb.refs);
13154
13155         /* ilgen is no longer needed */
13156         mb->ilgen = NULL;
13157
13158         domain = mono_domain_get ();
13159         mono_domain_lock (domain);
13160         if (!domain->method_to_dyn_method)
13161                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13162         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13163         mono_domain_unlock (domain);
13164 }
13165
13166 #endif /* DISABLE_REFLECTION_EMIT */
13167
13168 /**
13169  * 
13170  * mono_reflection_is_valid_dynamic_token:
13171  * 
13172  * Returns TRUE if token is valid.
13173  * 
13174  */
13175 gboolean
13176 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13177 {
13178         return lookup_dyn_token (image, token) != NULL;
13179 }
13180
13181 MonoMethodSignature *
13182 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13183 {
13184         MonoMethodSignature *sig;
13185         g_assert (image_is_dynamic (image));
13186
13187         mono_error_init (error);
13188
13189         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13190         if (sig)
13191                 return sig;
13192
13193         return mono_method_signature_checked (method, error);
13194 }
13195
13196 #ifndef DISABLE_REFLECTION_EMIT
13197
13198 /**
13199  * mono_reflection_lookup_dynamic_token:
13200  *
13201  * Finish the Builder object pointed to by TOKEN and return the corresponding
13202  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13203  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13204  * mapping table.
13205  *
13206  * LOCKING: Take the loader lock
13207  */
13208 gpointer
13209 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13210 {
13211         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13212         MonoObject *obj;
13213         MonoClass *klass;
13214
13215         obj = lookup_dyn_token (assembly, token);
13216         if (!obj) {
13217                 if (valid_token)
13218                         g_error ("Could not find required dynamic token 0x%08x", token);
13219                 else
13220                         return NULL;
13221         }
13222
13223         if (!handle_class)
13224                 handle_class = &klass;
13225         return resolve_object (image, obj, handle_class, context);
13226 }
13227
13228 /*
13229  * ensure_complete_type:
13230  *
13231  *   Ensure that KLASS is completed if it is a dynamic type, or references
13232  * dynamic types.
13233  */
13234 static void
13235 ensure_complete_type (MonoClass *klass)
13236 {
13237         MonoError error;
13238
13239         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13240                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13241
13242                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13243                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13244
13245                 // Asserting here could break a lot of code
13246                 //g_assert (klass->wastypebuilder);
13247         }
13248
13249         if (klass->generic_class) {
13250                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13251                 int i;
13252
13253                 for (i = 0; i < inst->type_argc; ++i) {
13254                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13255                 }
13256         }
13257 }
13258
13259 static gpointer
13260 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13261 {
13262         MonoError error;
13263         gpointer result = NULL;
13264
13265         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13266                 result = mono_string_intern_checked ((MonoString*)obj, &error);
13267                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13268                 *handle_class = mono_defaults.string_class;
13269                 g_assert (result);
13270         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13271                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13272                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13273                 MonoClass *mc = mono_class_from_mono_type (type);
13274                 if (!mono_class_init (mc))
13275                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
13276
13277                 if (context) {
13278                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13279                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13280
13281                         result = mono_class_from_mono_type (inflated);
13282                         mono_metadata_free_type (inflated);
13283                 } else {
13284                         result = mono_class_from_mono_type (type);
13285                 }
13286                 *handle_class = mono_defaults.typehandle_class;
13287                 g_assert (result);
13288         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13289                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13290                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13291                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13292                 result = ((MonoReflectionMethod*)obj)->method;
13293                 if (context) {
13294                         MonoError error;
13295                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13296                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13297                 }
13298                 *handle_class = mono_defaults.methodhandle_class;
13299                 g_assert (result);
13300         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13301                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13302                 result = mb->mhandle;
13303                 if (!result) {
13304                         /* Type is not yet created */
13305                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13306
13307                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13308                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13309
13310                         /*
13311                          * Hopefully this has been filled in by calling CreateType() on the
13312                          * TypeBuilder.
13313                          */
13314                         /*
13315                          * TODO: This won't work if the application finishes another 
13316                          * TypeBuilder instance instead of this one.
13317                          */
13318                         result = mb->mhandle;
13319                 }
13320                 if (context) {
13321                         MonoError error;
13322                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13323                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13324                 }
13325                 *handle_class = mono_defaults.methodhandle_class;
13326         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13327                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13328
13329                 result = cb->mhandle;
13330                 if (!result) {
13331                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13332
13333                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13334                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13335                         result = cb->mhandle;
13336                 }
13337                 if (context) {
13338                         MonoError error;
13339                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13340                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13341                 }
13342                 *handle_class = mono_defaults.methodhandle_class;
13343         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13344                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13345
13346                 ensure_complete_type (field->parent);
13347                 if (context) {
13348                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13349                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13350
13351                         MonoClass *klass = mono_class_from_mono_type (inflated);
13352                         MonoClassField *inflated_field;
13353                         gpointer iter = NULL;
13354                         mono_metadata_free_type (inflated);
13355                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13356                                 if (!strcmp (field->name, inflated_field->name))
13357                                         break;
13358                         }
13359                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13360                         result = inflated_field;
13361                 } else {
13362                         result = field;
13363                 }
13364                 *handle_class = mono_defaults.fieldhandle_class;
13365                 g_assert (result);
13366         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13367                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13368                 result = fb->handle;
13369
13370                 if (!result) {
13371                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13372
13373                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13374                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13375                         result = fb->handle;
13376                 }
13377
13378                 if (fb->handle && fb->handle->parent->generic_container) {
13379                         MonoClass *klass = fb->handle->parent;
13380                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13381                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13382
13383                         MonoClass *inflated = mono_class_from_mono_type (type);
13384
13385                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13386                         g_assert (result);
13387                         mono_metadata_free_type (type);
13388                 }
13389                 *handle_class = mono_defaults.fieldhandle_class;
13390         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13391                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13392                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13393                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13394                 MonoClass *klass;
13395
13396                 klass = type->data.klass;
13397                 if (klass->wastypebuilder) {
13398                         /* Already created */
13399                         result = klass;
13400                 }
13401                 else {
13402                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13403                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13404                         result = type->data.klass;
13405                         g_assert (result);
13406                 }
13407                 *handle_class = mono_defaults.typehandle_class;
13408         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13409                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13410                 MonoMethodSignature *sig;
13411                 int nargs, i;
13412
13413                 if (helper->arguments)
13414                         nargs = mono_array_length (helper->arguments);
13415                 else
13416                         nargs = 0;
13417
13418                 sig = mono_metadata_signature_alloc (image, nargs);
13419                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13420                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13421
13422                 if (helper->unmanaged_call_conv) { /* unmanaged */
13423                         sig->call_convention = helper->unmanaged_call_conv - 1;
13424                         sig->pinvoke = TRUE;
13425                 } else if (helper->call_conv & 0x02) {
13426                         sig->call_convention = MONO_CALL_VARARG;
13427                 } else {
13428                         sig->call_convention = MONO_CALL_DEFAULT;
13429                 }
13430
13431                 sig->param_count = nargs;
13432                 /* TODO: Copy type ? */
13433                 sig->ret = helper->return_type->type;
13434                 for (i = 0; i < nargs; ++i) {
13435                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13436                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13437                 }
13438
13439                 result = sig;
13440                 *handle_class = NULL;
13441         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13442                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13443                 /* Already created by the managed code */
13444                 g_assert (method->mhandle);
13445                 result = method->mhandle;
13446                 *handle_class = mono_defaults.methodhandle_class;
13447         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13448                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13449                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13450                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13451                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13452
13453                 result = mono_class_from_mono_type (type);
13454                 *handle_class = mono_defaults.typehandle_class;
13455                 g_assert (result);
13456                 mono_metadata_free_type (type);
13457         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13458                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13459                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13460                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13461                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13462
13463                 result = mono_class_from_mono_type (type);
13464                 *handle_class = mono_defaults.typehandle_class;
13465                 g_assert (result);
13466                 mono_metadata_free_type (type);
13467         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13468                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13469                 MonoClass *inflated;
13470                 MonoType *type;
13471                 MonoClassField *field;
13472
13473                 if (is_sre_field_builder (mono_object_class (f->fb)))
13474                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13475                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13476                         field = ((MonoReflectionField*)f->fb)->field;
13477                 else
13478                         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)));
13479
13480                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13481                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13482                 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13483                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13484
13485                 inflated = mono_class_from_mono_type (type);
13486
13487                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13488                 ensure_complete_type (field->parent);
13489                 g_assert (result);
13490                 mono_metadata_free_type (type);
13491                 *handle_class = mono_defaults.fieldhandle_class;
13492         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13493                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13494                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13495                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13496                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13497                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13498
13499                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13500                 MonoMethod *method;
13501
13502                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13503                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13504                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13505                         method = ((MonoReflectionMethod *)c->cb)->method;
13506                 else
13507                         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)));
13508
13509                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13510                 *handle_class = mono_defaults.methodhandle_class;
13511                 mono_metadata_free_type (type);
13512         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13513                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13514                 if (m->method_args) {
13515                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13516                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13517                         if (context) {
13518                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13519                                 mono_error_assert_ok (&error);
13520                         }
13521                 } else {
13522                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13523                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13524                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13525                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13526
13527                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
13528                         MonoMethod *method;
13529
13530                         if (is_sre_method_builder (mono_object_class (m->mb)))
13531                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13532                         else if (is_sr_mono_method (mono_object_class (m->mb)))
13533                                 method = ((MonoReflectionMethod *)m->mb)->method;
13534                         else
13535                                 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)));
13536
13537                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13538                         mono_metadata_free_type (type);
13539                 }
13540                 *handle_class = mono_defaults.methodhandle_class;
13541         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13542                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13543                 MonoType *mtype;
13544                 MonoClass *klass;
13545                 MonoMethod *method;
13546                 gpointer iter;
13547                 char *name;
13548
13549                 mtype = mono_reflection_type_get_handle (m->parent, &error);
13550                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13551                 klass = mono_class_from_mono_type (mtype);
13552
13553                 /* Find the method */
13554
13555                 name = mono_string_to_utf8 (m->name);
13556                 iter = NULL;
13557                 while ((method = mono_class_get_methods (klass, &iter))) {
13558                         if (!strcmp (method->name, name))
13559                                 break;
13560                 }
13561                 g_free (name);
13562
13563                 // FIXME:
13564                 g_assert (method);
13565                 // FIXME: Check parameters/return value etc. match
13566
13567                 result = method;
13568                 *handle_class = mono_defaults.methodhandle_class;
13569         } else if (is_sre_array (mono_object_get_class(obj)) ||
13570                                 is_sre_byref (mono_object_get_class(obj)) ||
13571                                 is_sre_pointer (mono_object_get_class(obj))) {
13572                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13573                 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13574                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13575
13576                 if (context) {
13577                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13578                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13579
13580                         result = mono_class_from_mono_type (inflated);
13581                         mono_metadata_free_type (inflated);
13582                 } else {
13583                         result = mono_class_from_mono_type (type);
13584                 }
13585                 *handle_class = mono_defaults.typehandle_class;
13586         } else {
13587                 g_print ("%s\n", obj->vtable->klass->name);
13588                 g_assert_not_reached ();
13589         }
13590         return result;
13591 }
13592
13593 #else /* DISABLE_REFLECTION_EMIT */
13594
13595 MonoArray*
13596 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
13597 {
13598         g_assert_not_reached ();
13599         return NULL;
13600 }
13601
13602 void
13603 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13604 {
13605         g_assert_not_reached ();
13606 }
13607
13608 void
13609 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13610 {
13611         g_assert_not_reached ();
13612 }
13613
13614 void
13615 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13616 {
13617         g_assert_not_reached ();
13618 }
13619
13620 void
13621 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13622 {
13623         g_assert_not_reached ();
13624 }
13625
13626 void
13627 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13628 {
13629         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13630 }
13631
13632 void
13633 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13634 {
13635         g_assert_not_reached ();
13636 }
13637
13638 void
13639 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13640 {
13641         g_assert_not_reached ();
13642 }
13643
13644 MonoReflectionModule *
13645 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13646 {
13647         g_assert_not_reached ();
13648         return NULL;
13649 }
13650
13651 guint32
13652 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13653 {
13654         g_assert_not_reached ();
13655         return 0;
13656 }
13657
13658 guint32
13659 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13660 {
13661         g_assert_not_reached ();
13662         return 0;
13663 }
13664
13665 guint32
13666 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
13667                          gboolean create_open_instance, gboolean register_token, MonoError *error)
13668 {
13669         g_assert_not_reached ();
13670         return 0;
13671 }
13672
13673 void
13674 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13675 {
13676 }
13677
13678 void
13679 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13680 {
13681         g_assert_not_reached ();
13682 }
13683
13684 void
13685 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13686 {
13687         *overrides = NULL;
13688         *num_overrides = 0;
13689 }
13690
13691 MonoReflectionEvent *
13692 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13693 {
13694         g_assert_not_reached ();
13695         return NULL;
13696 }
13697
13698 MonoReflectionType*
13699 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13700 {
13701         g_assert_not_reached ();
13702         return NULL;
13703 }
13704
13705 void
13706 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13707 {
13708         g_assert_not_reached ();
13709 }
13710
13711 MonoArray *
13712 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13713 {
13714         g_assert_not_reached ();
13715         return NULL;
13716 }
13717
13718 MonoArray *
13719 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13720 {
13721         g_assert_not_reached ();
13722         return NULL;
13723 }
13724
13725 void 
13726 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13727 {
13728 }
13729
13730 gpointer
13731 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13732 {
13733         return NULL;
13734 }
13735
13736 MonoType*
13737 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
13738 {
13739         mono_error_init (error);
13740         if (!ref)
13741                 return NULL;
13742         return ref->type;
13743 }
13744
13745 void
13746 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13747 {
13748         g_assert_not_reached ();
13749 }
13750
13751 #endif /* DISABLE_REFLECTION_EMIT */
13752
13753 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13754 const static guint32 declsec_flags_map[] = {
13755         0x00000000,                                     /* empty */
13756         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
13757         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
13758         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
13759         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
13760         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
13761         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
13762         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
13763         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
13764         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
13765         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
13766         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
13767         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
13768         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
13769         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
13770         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
13771         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
13772         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
13773         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
13774 };
13775
13776 /*
13777  * Returns flags that includes all available security action associated to the handle.
13778  * @token: metadata token (either for a class or a method)
13779  * @image: image where resides the metadata.
13780  */
13781 static guint32
13782 mono_declsec_get_flags (MonoImage *image, guint32 token)
13783 {
13784         int index = mono_metadata_declsec_from_index (image, token);
13785         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13786         guint32 result = 0;
13787         guint32 action;
13788         int i;
13789
13790         /* HasSecurity can be present for other, not specially encoded, attributes,
13791            e.g. SuppressUnmanagedCodeSecurityAttribute */
13792         if (index < 0)
13793                 return 0;
13794
13795         for (i = index; i < t->rows; i++) {
13796                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13797
13798                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13799                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13800                         break;
13801
13802                 action = cols [MONO_DECL_SECURITY_ACTION];
13803                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13804                         result |= declsec_flags_map [action];
13805                 } else {
13806                         g_assert_not_reached ();
13807                 }
13808         }
13809         return result;
13810 }
13811
13812 /*
13813  * Get the security actions (in the form of flags) associated with the specified method.
13814  *
13815  * @method: The method for which we want the declarative security flags.
13816  * Return the declarative security flags for the method (only).
13817  *
13818  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13819  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13820  */
13821 guint32
13822 mono_declsec_flags_from_method (MonoMethod *method)
13823 {
13824         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13825                 /* FIXME: No cache (for the moment) */
13826                 guint32 idx = mono_method_get_index (method);
13827                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13828                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13829                 return mono_declsec_get_flags (method->klass->image, idx);
13830         }
13831         return 0;
13832 }
13833
13834 /*
13835  * Get the security actions (in the form of flags) associated with the specified class.
13836  *
13837  * @klass: The class for which we want the declarative security flags.
13838  * Return the declarative security flags for the class.
13839  *
13840  * Note: We cache the flags inside the MonoClass structure as this will get 
13841  *       called very often (at least for each method).
13842  */
13843 guint32
13844 mono_declsec_flags_from_class (MonoClass *klass)
13845 {
13846         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13847                 if (!klass->ext || !klass->ext->declsec_flags) {
13848                         guint32 idx;
13849
13850                         idx = mono_metadata_token_index (klass->type_token);
13851                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13852                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13853                         mono_loader_lock ();
13854                         mono_class_alloc_ext (klass);
13855                         mono_loader_unlock ();
13856                         /* we cache the flags on classes */
13857                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13858                 }
13859                 return klass->ext->declsec_flags;
13860         }
13861         return 0;
13862 }
13863
13864 /*
13865  * Get the security actions (in the form of flags) associated with the specified assembly.
13866  *
13867  * @assembly: The assembly for which we want the declarative security flags.
13868  * Return the declarative security flags for the assembly.
13869  */
13870 guint32
13871 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13872 {
13873         guint32 idx = 1; /* there is only one assembly */
13874         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13875         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13876         return mono_declsec_get_flags (assembly->image, idx);
13877 }
13878
13879
13880 /*
13881  * Fill actions for the specific index (which may either be an encoded class token or
13882  * an encoded method token) from the metadata image.
13883  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13884  */
13885 static MonoBoolean
13886 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13887         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13888 {
13889         MonoBoolean result = FALSE;
13890         MonoTableInfo *t;
13891         guint32 cols [MONO_DECL_SECURITY_SIZE];
13892         int index = mono_metadata_declsec_from_index (image, token);
13893         int i;
13894
13895         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13896         for (i = index; i < t->rows; i++) {
13897                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13898
13899                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13900                         return result;
13901
13902                 /* if present only replace (class) permissions with method permissions */
13903                 /* if empty accept either class or method permissions */
13904                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13905                         if (!actions->demand.blob) {
13906                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13907                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13908                                 actions->demand.blob = (char*) (blob + 2);
13909                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13910                                 result = TRUE;
13911                         }
13912                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13913                         if (!actions->noncasdemand.blob) {
13914                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13915                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13916                                 actions->noncasdemand.blob = (char*) (blob + 2);
13917                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13918                                 result = TRUE;
13919                         }
13920                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13921                         if (!actions->demandchoice.blob) {
13922                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13923                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13924                                 actions->demandchoice.blob = (char*) (blob + 2);
13925                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13926                                 result = TRUE;
13927                         }
13928                 }
13929         }
13930
13931         return result;
13932 }
13933
13934 static MonoBoolean
13935 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
13936         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13937 {
13938         guint32 idx = mono_metadata_token_index (klass->type_token);
13939         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13940         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13941         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13942 }
13943
13944 static MonoBoolean
13945 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
13946         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13947 {
13948         guint32 idx = mono_method_get_index (method);
13949         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13950         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13951         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13952 }
13953
13954 /*
13955  * Collect all actions (that requires to generate code in mini) assigned for
13956  * the specified method.
13957  * Note: Don't use the content of actions if the function return FALSE.
13958  */
13959 MonoBoolean
13960 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13961 {
13962         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
13963                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13964         MonoBoolean result = FALSE;
13965         guint32 flags;
13966
13967         /* quick exit if no declarative security is present in the metadata */
13968         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13969                 return FALSE;
13970
13971         /* we want the original as the wrapper is "free" of the security informations */
13972         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13973                 method = mono_marshal_method_from_wrapper (method);
13974                 if (!method)
13975                         return FALSE;
13976         }
13977
13978         /* First we look for method-level attributes */
13979         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13980                 mono_class_init (method->klass);
13981                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13982
13983                 result = mono_declsec_get_method_demands_params (method, demands, 
13984                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13985         }
13986
13987         /* Here we use (or create) the class declarative cache to look for demands */
13988         flags = mono_declsec_flags_from_class (method->klass);
13989         if (flags & mask) {
13990                 if (!result) {
13991                         mono_class_init (method->klass);
13992                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
13993                 }
13994                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
13995                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13996         }
13997
13998         /* The boolean return value is used as a shortcut in case nothing needs to
13999            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14000         return result;
14001 }
14002
14003
14004 /*
14005  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14006  *
14007  * Note: Don't use the content of actions if the function return FALSE.
14008  */
14009 MonoBoolean
14010 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14011 {
14012         MonoBoolean result = FALSE;
14013         guint32 flags;
14014
14015         /* quick exit if no declarative security is present in the metadata */
14016         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14017                 return FALSE;
14018
14019         /* we want the original as the wrapper is "free" of the security informations */
14020         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14021                 method = mono_marshal_method_from_wrapper (method);
14022                 if (!method)
14023                         return FALSE;
14024         }
14025
14026         /* results are independant - zeroize both */
14027         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14028         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14029
14030         /* First we look for method-level attributes */
14031         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14032                 mono_class_init (method->klass);
14033
14034                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14035                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14036         }
14037
14038         /* Here we use (or create) the class declarative cache to look for demands */
14039         flags = mono_declsec_flags_from_class (method->klass);
14040         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14041                 mono_class_init (method->klass);
14042
14043                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14044                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14045         }
14046
14047         return result;
14048 }
14049
14050 /*
14051  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14052  *
14053  * @klass       The inherited class - this is the class that provides the security check (attributes)
14054  * @demans      
14055  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14056  * 
14057  * Note: Don't use the content of actions if the function return FALSE.
14058  */
14059 MonoBoolean
14060 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14061 {
14062         MonoBoolean result = FALSE;
14063         guint32 flags;
14064
14065         /* quick exit if no declarative security is present in the metadata */
14066         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14067                 return FALSE;
14068
14069         /* Here we use (or create) the class declarative cache to look for demands */
14070         flags = mono_declsec_flags_from_class (klass);
14071         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14072                 mono_class_init (klass);
14073                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14074
14075                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14076                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14077         }
14078
14079         return result;
14080 }
14081
14082 /*
14083  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14084  *
14085  * Note: Don't use the content of actions if the function return FALSE.
14086  */
14087 MonoBoolean
14088 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14089 {
14090         /* quick exit if no declarative security is present in the metadata */
14091         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14092                 return FALSE;
14093
14094         /* we want the original as the wrapper is "free" of the security informations */
14095         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14096                 method = mono_marshal_method_from_wrapper (method);
14097                 if (!method)
14098                         return FALSE;
14099         }
14100
14101         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14102                 mono_class_init (method->klass);
14103                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14104
14105                 return mono_declsec_get_method_demands_params (method, demands, 
14106                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14107         }
14108         return FALSE;
14109 }
14110
14111
14112 static MonoBoolean
14113 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14114 {
14115         guint32 cols [MONO_DECL_SECURITY_SIZE];
14116         MonoTableInfo *t;
14117         int i;
14118
14119         int index = mono_metadata_declsec_from_index (image, token);
14120         if (index == -1)
14121                 return FALSE;
14122
14123         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14124         for (i = index; i < t->rows; i++) {
14125                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14126
14127                 /* shortcut - index are ordered */
14128                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14129                         return FALSE;
14130
14131                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14132                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14133                         entry->blob = (char*) (metadata + 2);
14134                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14135                         return TRUE;
14136                 }
14137         }
14138
14139         return FALSE;
14140 }
14141
14142 MonoBoolean
14143 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14144 {
14145         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14146                 guint32 idx = mono_method_get_index (method);
14147                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14148                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14149                 return get_declsec_action (method->klass->image, idx, action, entry);
14150         }
14151         return FALSE;
14152 }
14153
14154 MonoBoolean
14155 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14156 {
14157         /* use cache */
14158         guint32 flags = mono_declsec_flags_from_class (klass);
14159         if (declsec_flags_map [action] & flags) {
14160                 guint32 idx = mono_metadata_token_index (klass->type_token);
14161                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14162                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14163                 return get_declsec_action (klass->image, idx, action, entry);
14164         }
14165         return FALSE;
14166 }
14167
14168 MonoBoolean
14169 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14170 {
14171         guint32 idx = 1; /* there is only one assembly */
14172         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14173         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14174
14175         return get_declsec_action (assembly->image, idx, action, entry);
14176 }
14177
14178 gboolean
14179 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14180 {
14181         MonoError error;
14182         MonoObject *res, *exc;
14183         void *params [1];
14184         static MonoMethod *method = NULL;
14185
14186         if (method == NULL) {
14187                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14188                 g_assert (method);
14189         }
14190
14191         /* 
14192          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14193          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14194          */
14195         g_assert (mono_class_get_ref_info (klass));
14196         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14197
14198         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14199         mono_error_raise_exception (&error); /* FIXME don't raise here */
14200
14201         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14202
14203         if (exc || !mono_error_ok (&error)) {
14204                 mono_error_cleanup (&error);
14205                 return FALSE;
14206         } else
14207                 return *(MonoBoolean*)mono_object_unbox (res);
14208 }
14209
14210 /**
14211  * mono_reflection_type_get_type:
14212  * @reftype: the System.Type object
14213  *
14214  * Returns the MonoType* associated with the C# System.Type object @reftype.
14215  */
14216 MonoType*
14217 mono_reflection_type_get_type (MonoReflectionType *reftype)
14218 {
14219         g_assert (reftype);
14220
14221         MonoError error;
14222         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14223         mono_error_assert_ok (&error);
14224         return result;
14225 }
14226
14227 /**
14228  * mono_reflection_assembly_get_assembly:
14229  * @refassembly: the System.Reflection.Assembly object
14230  *
14231  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14232  */
14233 MonoAssembly*
14234 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14235 {
14236         g_assert (refassembly);
14237
14238         return refassembly->assembly;
14239 }
14240