[reflection] Don't crash when building dynamic custom attributes on dynamic types...
[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  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13 #include <config.h>
14 #include "mono/utils/mono-digest.h"
15 #include "mono/utils/mono-membar.h"
16 #include "mono/metadata/reflection-internals.h"
17 #include "mono/metadata/tabledefs.h"
18 #include "mono/metadata/metadata-internals.h"
19 #include <mono/metadata/profiler-private.h>
20 #include "mono/metadata/class-internals.h"
21 #include "mono/metadata/gc-internals.h"
22 #include "mono/metadata/tokentype.h"
23 #include "mono/metadata/domain-internals.h"
24 #include "mono/metadata/opcodes.h"
25 #include "mono/metadata/assembly.h"
26 #include "mono/metadata/object-internals.h"
27 #include <mono/metadata/exception.h>
28 #include <mono/metadata/marshal.h>
29 #include <mono/metadata/security-manager.h>
30 #include <stdio.h>
31 #include <glib.h>
32 #include <errno.h>
33 #include <time.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "image.h"
37 #include "cil-coff.h"
38 #include "mono-endian.h"
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/mempool-internals.h>
41 #include <mono/metadata/security-core-clr.h>
42 #include <mono/metadata/debug-helpers.h>
43 #include <mono/metadata/verify-internals.h>
44 #include <mono/metadata/mono-ptr-array.h>
45 #include <mono/utils/mono-string.h>
46 #include <mono/utils/mono-error-internals.h>
47 #include <mono/utils/checked-build.h>
48
49 static gboolean is_usertype (MonoReflectionType *ref);
50 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
51
52 typedef struct {
53         char *p;
54         char *buf;
55         char *end;
56 } SigBuffer;
57
58 #define TEXT_OFFSET 512
59 #define CLI_H_SIZE 136
60 #define FILE_ALIGN 512
61 #define VIRT_ALIGN 8192
62 #define START_TEXT_RVA  0x00002000
63
64 typedef struct {
65         MonoReflectionILGen *ilgen;
66         MonoReflectionType *rtype;
67         MonoArray *parameters;
68         MonoArray *generic_params;
69         MonoGenericContainer *generic_container;
70         MonoArray *pinfo;
71         MonoArray *opt_types;
72         guint32 attrs;
73         guint32 iattrs;
74         guint32 call_conv;
75         guint32 *table_idx; /* note: it's a pointer */
76         MonoArray *code;
77         MonoObject *type;
78         MonoString *name;
79         MonoBoolean init_locals;
80         MonoBoolean skip_visibility;
81         MonoArray *return_modreq;
82         MonoArray *return_modopt;
83         MonoArray *param_modreq;
84         MonoArray *param_modopt;
85         MonoArray *permissions;
86         MonoMethod *mhandle;
87         guint32 nrefs;
88         gpointer *refs;
89         /* for PInvoke */
90         int charset, extra_flags, native_cc;
91         MonoString *dll, *dllentry;
92 } ReflectionMethodBuilder;
93
94 typedef struct {
95         guint32 owner;
96         MonoReflectionGenericParam *gparam;
97 } GenericParamTableEntry;
98
99 const unsigned char table_sizes [MONO_TABLE_NUM] = {
100         MONO_MODULE_SIZE,
101         MONO_TYPEREF_SIZE,
102         MONO_TYPEDEF_SIZE,
103         0,
104         MONO_FIELD_SIZE,
105         0,
106         MONO_METHOD_SIZE,
107         0,
108         MONO_PARAM_SIZE,
109         MONO_INTERFACEIMPL_SIZE,
110         MONO_MEMBERREF_SIZE,    /* 0x0A */
111         MONO_CONSTANT_SIZE,
112         MONO_CUSTOM_ATTR_SIZE,
113         MONO_FIELD_MARSHAL_SIZE,
114         MONO_DECL_SECURITY_SIZE,
115         MONO_CLASS_LAYOUT_SIZE,
116         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
117         MONO_STAND_ALONE_SIGNATURE_SIZE,
118         MONO_EVENT_MAP_SIZE,
119         0,
120         MONO_EVENT_SIZE,
121         MONO_PROPERTY_MAP_SIZE,
122         0,
123         MONO_PROPERTY_SIZE,
124         MONO_METHOD_SEMA_SIZE,
125         MONO_METHODIMPL_SIZE,
126         MONO_MODULEREF_SIZE,    /* 0x1A */
127         MONO_TYPESPEC_SIZE,
128         MONO_IMPLMAP_SIZE,      
129         MONO_FIELD_RVA_SIZE,
130         0,
131         0,
132         MONO_ASSEMBLY_SIZE,     /* 0x20 */
133         MONO_ASSEMBLY_PROCESSOR_SIZE,
134         MONO_ASSEMBLYOS_SIZE,
135         MONO_ASSEMBLYREF_SIZE,
136         MONO_ASSEMBLYREFPROC_SIZE,
137         MONO_ASSEMBLYREFOS_SIZE,
138         MONO_FILE_SIZE,
139         MONO_EXP_TYPE_SIZE,
140         MONO_MANIFEST_SIZE,
141         MONO_NESTED_CLASS_SIZE,
142
143         MONO_GENERICPARAM_SIZE, /* 0x2A */
144         MONO_METHODSPEC_SIZE,
145         MONO_GENPARCONSTRAINT_SIZE
146
147 };
148
149 #ifndef DISABLE_REFLECTION_EMIT
150 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
151 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
152 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
153 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
154 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
155 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
156 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
157 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
158 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
159 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
160 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
161 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
162 #endif
163
164 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
165 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
166 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
167 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
168 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
169 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
170 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
171 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
172 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
173 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
174 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
175 static gboolean is_sre_array (MonoClass *klass);
176 static gboolean is_sre_byref (MonoClass *klass);
177 static gboolean is_sre_pointer (MonoClass *klass);
178 static gboolean is_sre_type_builder (MonoClass *klass);
179 static gboolean is_sre_method_builder (MonoClass *klass);
180 static gboolean is_sre_ctor_builder (MonoClass *klass);
181 static gboolean is_sre_field_builder (MonoClass *klass);
182 static gboolean is_sr_mono_method (MonoClass *klass);
183 static gboolean is_sr_mono_cmethod (MonoClass *klass);
184 static gboolean is_sr_mono_generic_method (MonoClass *klass);
185 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
186 static gboolean is_sr_mono_field (MonoClass *klass);
187 static gboolean is_sr_mono_property (MonoClass *klass);
188 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
189 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190
191 static gboolean type_is_reference (MonoType *type);
192
193 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
194 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
195 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
196
197 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
198 static void init_type_builder_generics (MonoObject *type, MonoError *error);
199
200 #define RESOLVE_TYPE(type, error) do {                                  \
201         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
202 } while (0)
203 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
204         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
205         __type = mono_reflection_type_resolve_user_types (__type, error); \
206         if (mono_error_ok (error))                                      \
207                 mono_array_set (arr, MonoReflectionType*, index, __type); \
208 } while (0)
209
210 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
211
212 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
213 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
214
215 #if SIZEOF_VOID_P == 4
216 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
217 #else
218 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
219 #endif
220
221 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
222 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
223
224 /* Class lazy loading functions */
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
232 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
233 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
234 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
236 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
237 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
238 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
239 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
240 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
241 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
242 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
243 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
244
245 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
246 static GPtrArray *dynamic_images;
247 static mono_mutex_t dynamic_images_mutex;
248
249 static inline void
250 dynamic_images_lock (void)
251 {
252         mono_os_mutex_lock (&dynamic_images_mutex);
253 }
254
255 static inline void
256 dynamic_images_unlock (void)
257 {
258         mono_os_mutex_unlock (&dynamic_images_mutex);
259 }
260
261 /**
262  * mono_find_dynamic_image_owner:
263  *
264  * Find the dynamic image, if any, which a given pointer is located in the memory of.
265  */
266 MonoImage *
267 mono_find_dynamic_image_owner (void *ptr)
268 {
269         MonoImage *owner = NULL;
270         int i;
271
272         dynamic_images_lock ();
273
274         if (dynamic_images)
275         {
276                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
277                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
278                         if (mono_mempool_contains_addr (image->mempool, ptr))
279                                 owner = image;
280                 }
281         }
282
283         dynamic_images_unlock ();
284
285         return owner;
286 }
287
288 void
289 mono_reflection_init (void)
290 {
291         mono_os_mutex_init (&dynamic_images_mutex);
292 }
293
294 static inline void
295 dynamic_image_lock (MonoDynamicImage *image)
296 {
297         MONO_ENTER_GC_SAFE;
298         mono_image_lock ((MonoImage*)image);
299         MONO_EXIT_GC_SAFE;
300 }
301
302 static inline void
303 dynamic_image_unlock (MonoDynamicImage *image)
304 {
305         mono_image_unlock ((MonoImage*)image);
306 }
307
308 static void
309 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
310 {
311         MONO_REQ_GC_UNSAFE_MODE;
312
313         dynamic_image_lock (assembly);
314         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
315         dynamic_image_unlock (assembly);
316 }
317
318 static MonoObject*
319 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
320 {
321         MONO_REQ_GC_UNSAFE_MODE;
322
323         MonoObject *obj;
324
325         dynamic_image_lock (assembly);
326         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
327         dynamic_image_unlock (assembly);
328
329         return obj;
330 }
331
332 static void
333 sigbuffer_init (SigBuffer *buf, int size)
334 {
335         MONO_REQ_GC_NEUTRAL_MODE;
336
337         buf->buf = (char *)g_malloc (size);
338         buf->p = buf->buf;
339         buf->end = buf->buf + size;
340 }
341
342 static void
343 sigbuffer_make_room (SigBuffer *buf, int size)
344 {
345         MONO_REQ_GC_NEUTRAL_MODE;
346
347         if (buf->end - buf->p < size) {
348                 int new_size = buf->end - buf->buf + size + 32;
349                 char *p = (char *)g_realloc (buf->buf, new_size);
350                 size = buf->p - buf->buf;
351                 buf->buf = p;
352                 buf->p = p + size;
353                 buf->end = buf->buf + new_size;
354         }
355 }
356
357 static void
358 sigbuffer_add_value (SigBuffer *buf, guint32 val)
359 {
360         MONO_REQ_GC_NEUTRAL_MODE;
361
362         sigbuffer_make_room (buf, 6);
363         mono_metadata_encode_value (val, buf->p, &buf->p);
364 }
365
366 static void
367 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
368 {
369         MONO_REQ_GC_NEUTRAL_MODE;
370
371         sigbuffer_make_room (buf, 1);
372         buf->p [0] = val;
373         buf->p++;
374 }
375
376 static void
377 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
378 {
379         MONO_REQ_GC_NEUTRAL_MODE;
380
381         sigbuffer_make_room (buf, size);
382         memcpy (buf->p, p, size);
383         buf->p += size;
384 }
385
386 static void
387 sigbuffer_free (SigBuffer *buf)
388 {
389         MONO_REQ_GC_NEUTRAL_MODE;
390
391         g_free (buf->buf);
392 }
393
394 #ifndef DISABLE_REFLECTION_EMIT
395 /**
396  * mp_g_alloc:
397  *
398  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
399  * from the C heap.
400  */
401 static gpointer
402 image_g_malloc (MonoImage *image, guint size)
403 {
404         MONO_REQ_GC_NEUTRAL_MODE;
405
406         if (image)
407                 return mono_image_alloc (image, size);
408         else
409                 return g_malloc (size);
410 }
411 #endif /* !DISABLE_REFLECTION_EMIT */
412
413 /**
414  * image_g_alloc0:
415  *
416  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
417  * from the C heap.
418  */
419 static gpointer
420 image_g_malloc0 (MonoImage *image, guint size)
421 {
422         MONO_REQ_GC_NEUTRAL_MODE;
423
424         if (image)
425                 return mono_image_alloc0 (image, size);
426         else
427                 return g_malloc0 (size);
428 }
429
430 /**
431  * image_g_free:
432  * @image: a MonoImage
433  * @ptr: pointer
434  *
435  * If @image is NULL, free @ptr, otherwise do nothing.
436  */
437 static void
438 image_g_free (MonoImage *image, gpointer ptr)
439 {
440         if (image == NULL)
441                 g_free (ptr);
442 }
443
444 #ifndef DISABLE_REFLECTION_EMIT
445 static char*
446 image_strdup (MonoImage *image, const char *s)
447 {
448         MONO_REQ_GC_NEUTRAL_MODE;
449
450         if (image)
451                 return mono_image_strdup (image, s);
452         else
453                 return g_strdup (s);
454 }
455 #endif
456
457 #define image_g_new(image,struct_type, n_structs)               \
458     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
459
460 #define image_g_new0(image,struct_type, n_structs)              \
461     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
462
463
464 static void
465 alloc_table (MonoDynamicTable *table, guint nrows)
466 {
467         MONO_REQ_GC_NEUTRAL_MODE;
468
469         table->rows = nrows;
470         g_assert (table->columns);
471         if (nrows + 1 >= table->alloc_rows) {
472                 while (nrows + 1 >= table->alloc_rows) {
473                         if (table->alloc_rows == 0)
474                                 table->alloc_rows = 16;
475                         else
476                                 table->alloc_rows *= 2;
477                 }
478
479                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
480         }
481 }
482
483 static void
484 make_room_in_stream (MonoDynamicStream *stream, int size)
485 {
486         MONO_REQ_GC_NEUTRAL_MODE;
487
488         if (size <= stream->alloc_size)
489                 return;
490         
491         while (stream->alloc_size <= size) {
492                 if (stream->alloc_size < 4096)
493                         stream->alloc_size = 4096;
494                 else
495                         stream->alloc_size *= 2;
496         }
497         
498         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
499 }
500
501 static guint32
502 string_heap_insert (MonoDynamicStream *sh, const char *str)
503 {
504         MONO_REQ_GC_NEUTRAL_MODE;
505
506         guint32 idx;
507         guint32 len;
508         gpointer oldkey, oldval;
509
510         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
511                 return GPOINTER_TO_UINT (oldval);
512
513         len = strlen (str) + 1;
514         idx = sh->index;
515         
516         make_room_in_stream (sh, idx + len);
517
518         /*
519          * We strdup the string even if we already copy them in sh->data
520          * so that the string pointers in the hash remain valid even if
521          * we need to realloc sh->data. We may want to avoid that later.
522          */
523         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
524         memcpy (sh->data + idx, str, len);
525         sh->index += len;
526         return idx;
527 }
528
529 static guint32
530 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
531 {
532         MONO_REQ_GC_UNSAFE_MODE;
533
534         mono_error_init (error);
535         char *name = mono_string_to_utf8_checked (str, error);
536         return_val_if_nok (error, -1);
537         guint32 idx;
538         idx = string_heap_insert (sh, name);
539         g_free (name);
540         return idx;
541 }
542
543 #ifndef DISABLE_REFLECTION_EMIT
544 static void
545 string_heap_init (MonoDynamicStream *sh)
546 {
547         MONO_REQ_GC_NEUTRAL_MODE;
548
549         sh->index = 0;
550         sh->alloc_size = 4096;
551         sh->data = (char *)g_malloc (4096);
552         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
553         string_heap_insert (sh, "");
554 }
555 #endif
556
557 static guint32
558 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
559 {
560         MONO_REQ_GC_NEUTRAL_MODE;
561
562         guint32 idx;
563         
564         make_room_in_stream (stream, stream->index + len);
565         memcpy (stream->data + stream->index, data, len);
566         idx = stream->index;
567         stream->index += len;
568         /* 
569          * align index? Not without adding an additional param that controls it since
570          * we may store a blob value in pieces.
571          */
572         return idx;
573 }
574
575 static guint32
576 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
577 {
578         MONO_REQ_GC_NEUTRAL_MODE;
579
580         guint32 idx;
581         
582         make_room_in_stream (stream, stream->index + len);
583         memset (stream->data + stream->index, 0, len);
584         idx = stream->index;
585         stream->index += len;
586         return idx;
587 }
588
589 static void
590 stream_data_align (MonoDynamicStream *stream)
591 {
592         MONO_REQ_GC_NEUTRAL_MODE;
593
594         char buf [4] = {0};
595         guint32 count = stream->index % 4;
596
597         /* we assume the stream data will be aligned */
598         if (count)
599                 mono_image_add_stream_data (stream, buf, 4 - count);
600 }
601
602 #ifndef DISABLE_REFLECTION_EMIT
603 static int
604 mono_blob_entry_hash (const char* str)
605 {
606         MONO_REQ_GC_NEUTRAL_MODE;
607
608         guint len, h;
609         const char *end;
610         len = mono_metadata_decode_blob_size (str, &str);
611         if (len > 0) {
612                 end = str + len;
613                 h = *str;
614                 for (str += 1; str < end; str++)
615                         h = (h << 5) - h + *str;
616                 return h;
617         } else {
618                 return 0;
619         }
620 }
621
622 static gboolean
623 mono_blob_entry_equal (const char *str1, const char *str2) {
624         MONO_REQ_GC_NEUTRAL_MODE;
625
626         int len, len2;
627         const char *end1;
628         const char *end2;
629         len = mono_metadata_decode_blob_size (str1, &end1);
630         len2 = mono_metadata_decode_blob_size (str2, &end2);
631         if (len != len2)
632                 return 0;
633         return memcmp (end1, end2, len) == 0;
634 }
635 #endif
636 static guint32
637 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
638 {
639         MONO_REQ_GC_NEUTRAL_MODE;
640
641         guint32 idx;
642         char *copy;
643         gpointer oldkey, oldval;
644
645         copy = (char *)g_malloc (s1+s2);
646         memcpy (copy, b1, s1);
647         memcpy (copy + s1, b2, s2);
648         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
649                 g_free (copy);
650                 idx = GPOINTER_TO_UINT (oldval);
651         } else {
652                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
653                 mono_image_add_stream_data (&assembly->blob, b2, s2);
654                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
655         }
656         return idx;
657 }
658
659 static guint32
660 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
661 {
662         MONO_REQ_GC_NEUTRAL_MODE;
663
664         char blob_size [8];
665         char *b = blob_size;
666         guint32 size = buf->p - buf->buf;
667         /* store length */
668         g_assert (size <= (buf->end - buf->buf));
669         mono_metadata_encode_value (size, b, &b);
670         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
671 }
672
673 /*
674  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
675  * dest may be misaligned.
676  */
677 static void
678 swap_with_size (char *dest, const char* val, int len, int nelem) {
679         MONO_REQ_GC_NEUTRAL_MODE;
680 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
681         int elem;
682
683         for (elem = 0; elem < nelem; ++elem) {
684                 switch (len) {
685                 case 1:
686                         *dest = *val;
687                         break;
688                 case 2:
689                         dest [0] = val [1];
690                         dest [1] = val [0];
691                         break;
692                 case 4:
693                         dest [0] = val [3];
694                         dest [1] = val [2];
695                         dest [2] = val [1];
696                         dest [3] = val [0];
697                         break;
698                 case 8:
699                         dest [0] = val [7];
700                         dest [1] = val [6];
701                         dest [2] = val [5];
702                         dest [3] = val [4];
703                         dest [4] = val [3];
704                         dest [5] = val [2];
705                         dest [6] = val [1];
706                         dest [7] = val [0];
707                         break;
708                 default:
709                         g_assert_not_reached ();
710                 }
711                 dest += len;
712                 val += len;
713         }
714 #else
715         memcpy (dest, val, len * nelem);
716 #endif
717 }
718
719 static guint32
720 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
721 {
722         MONO_REQ_GC_UNSAFE_MODE;
723         
724         char blob_size [64];
725         char *b = blob_size;
726         guint32 idx = 0, len;
727
728         len = str->length * 2;
729         mono_metadata_encode_value (len, b, &b);
730 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
731         {
732                 char *swapped = g_malloc (2 * mono_string_length (str));
733                 const char *p = (const char*)mono_string_chars (str);
734
735                 swap_with_size (swapped, p, 2, mono_string_length (str));
736                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
737                 g_free (swapped);
738         }
739 #else
740         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
741 #endif
742         return idx;
743 }
744
745 #ifndef DISABLE_REFLECTION_EMIT
746 static MonoClass *
747 default_class_from_mono_type (MonoType *type)
748 {
749         MONO_REQ_GC_NEUTRAL_MODE;
750
751         switch (type->type) {
752         case MONO_TYPE_OBJECT:
753                 return mono_defaults.object_class;
754         case MONO_TYPE_VOID:
755                 return mono_defaults.void_class;
756         case MONO_TYPE_BOOLEAN:
757                 return mono_defaults.boolean_class;
758         case MONO_TYPE_CHAR:
759                 return mono_defaults.char_class;
760         case MONO_TYPE_I1:
761                 return mono_defaults.sbyte_class;
762         case MONO_TYPE_U1:
763                 return mono_defaults.byte_class;
764         case MONO_TYPE_I2:
765                 return mono_defaults.int16_class;
766         case MONO_TYPE_U2:
767                 return mono_defaults.uint16_class;
768         case MONO_TYPE_I4:
769                 return mono_defaults.int32_class;
770         case MONO_TYPE_U4:
771                 return mono_defaults.uint32_class;
772         case MONO_TYPE_I:
773                 return mono_defaults.int_class;
774         case MONO_TYPE_U:
775                 return mono_defaults.uint_class;
776         case MONO_TYPE_I8:
777                 return mono_defaults.int64_class;
778         case MONO_TYPE_U8:
779                 return mono_defaults.uint64_class;
780         case MONO_TYPE_R4:
781                 return mono_defaults.single_class;
782         case MONO_TYPE_R8:
783                 return mono_defaults.double_class;
784         case MONO_TYPE_STRING:
785                 return mono_defaults.string_class;
786         default:
787                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
788                 g_assert_not_reached ();
789         }
790         
791         return NULL;
792 }
793 #endif
794
795 /*
796  * mono_class_get_ref_info:
797  *
798  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
799  */
800 gpointer
801 mono_class_get_ref_info (MonoClass *klass)
802 {
803         MONO_REQ_GC_UNSAFE_MODE;
804
805         if (klass->ref_info_handle == 0)
806                 return NULL;
807         else
808                 return mono_gchandle_get_target (klass->ref_info_handle);
809 }
810
811 void
812 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
813 {
814         MONO_REQ_GC_UNSAFE_MODE;
815
816         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
817         g_assert (klass->ref_info_handle != 0);
818 }
819
820 void
821 mono_class_free_ref_info (MonoClass *klass)
822 {
823         MONO_REQ_GC_NEUTRAL_MODE;
824
825         if (klass->ref_info_handle) {
826                 mono_gchandle_free (klass->ref_info_handle);
827                 klass->ref_info_handle = 0;
828         }
829 }
830
831 static void
832 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
833 {
834         MONO_REQ_GC_NEUTRAL_MODE;
835
836         int i;
837         MonoGenericInst *class_inst;
838         MonoClass *klass;
839
840         g_assert (gclass);
841
842         class_inst = gclass->context.class_inst;
843
844         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
845         klass = gclass->container_class;
846         sigbuffer_add_value (buf, klass->byval_arg.type);
847         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
848
849         sigbuffer_add_value (buf, class_inst->type_argc);
850         for (i = 0; i < class_inst->type_argc; ++i)
851                 encode_type (assembly, class_inst->type_argv [i], buf);
852
853 }
854
855 static void
856 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
857 {
858         MONO_REQ_GC_NEUTRAL_MODE;
859
860         if (!type) {
861                 g_assert_not_reached ();
862                 return;
863         }
864                 
865         if (type->byref)
866                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
867
868         switch (type->type){
869         case MONO_TYPE_VOID:
870         case MONO_TYPE_BOOLEAN:
871         case MONO_TYPE_CHAR:
872         case MONO_TYPE_I1:
873         case MONO_TYPE_U1:
874         case MONO_TYPE_I2:
875         case MONO_TYPE_U2:
876         case MONO_TYPE_I4:
877         case MONO_TYPE_U4:
878         case MONO_TYPE_I8:
879         case MONO_TYPE_U8:
880         case MONO_TYPE_R4:
881         case MONO_TYPE_R8:
882         case MONO_TYPE_I:
883         case MONO_TYPE_U:
884         case MONO_TYPE_STRING:
885         case MONO_TYPE_OBJECT:
886         case MONO_TYPE_TYPEDBYREF:
887                 sigbuffer_add_value (buf, type->type);
888                 break;
889         case MONO_TYPE_PTR:
890                 sigbuffer_add_value (buf, type->type);
891                 encode_type (assembly, type->data.type, buf);
892                 break;
893         case MONO_TYPE_SZARRAY:
894                 sigbuffer_add_value (buf, type->type);
895                 encode_type (assembly, &type->data.klass->byval_arg, buf);
896                 break;
897         case MONO_TYPE_VALUETYPE:
898         case MONO_TYPE_CLASS: {
899                 MonoClass *k = mono_class_from_mono_type (type);
900
901                 if (k->generic_container) {
902                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
903                         encode_generic_class (assembly, gclass, buf);
904                 } else {
905                         /*
906                          * Make sure we use the correct type.
907                          */
908                         sigbuffer_add_value (buf, k->byval_arg.type);
909                         /*
910                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
911                          * otherwise two typerefs could point to the same type, leading to
912                          * verification errors.
913                          */
914                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
915                 }
916                 break;
917         }
918         case MONO_TYPE_ARRAY:
919                 sigbuffer_add_value (buf, type->type);
920                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
921                 sigbuffer_add_value (buf, type->data.array->rank);
922                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
923                 sigbuffer_add_value (buf, 0);
924                 break;
925         case MONO_TYPE_GENERICINST:
926                 encode_generic_class (assembly, type->data.generic_class, buf);
927                 break;
928         case MONO_TYPE_VAR:
929         case MONO_TYPE_MVAR:
930                 sigbuffer_add_value (buf, type->type);
931                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
932                 break;
933         default:
934                 g_error ("need to encode type %x", type->type);
935         }
936 }
937
938 static void
939 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
940 {
941         MONO_REQ_GC_UNSAFE_MODE;
942
943         mono_error_init (error);
944
945         if (!type) {
946                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
947                 return;
948         }
949
950         MonoType *t = mono_reflection_type_get_handle (type, error);
951         return_if_nok (error);
952         encode_type (assembly, t, buf);
953 }
954
955 static void
956 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
957 {
958         MONO_REQ_GC_UNSAFE_MODE;
959
960         int i;
961
962         mono_error_init (error);
963
964         if (modreq) {
965                 for (i = 0; i < mono_array_length (modreq); ++i) {
966                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
967                         return_if_nok (error);
968                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
969                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
970                 }
971         }
972         if (modopt) {
973                 for (i = 0; i < mono_array_length (modopt); ++i) {
974                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
975                         return_if_nok (error);
976                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
977                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
978                 }
979         }
980 }
981
982 #ifndef DISABLE_REFLECTION_EMIT
983 static guint32
984 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
985 {
986         MONO_REQ_GC_UNSAFE_MODE;
987
988         SigBuffer buf;
989         int i;
990         guint32 nparams =  sig->param_count;
991         guint32 idx;
992
993         if (!assembly->save)
994                 return 0;
995
996         sigbuffer_init (&buf, 32);
997         /*
998          * FIXME: vararg, explicit_this, differenc call_conv values...
999          */
1000         idx = sig->call_convention;
1001         if (sig->hasthis)
1002                 idx |= 0x20; /* hasthis */
1003         if (sig->generic_param_count)
1004                 idx |= 0x10; /* generic */
1005         sigbuffer_add_byte (&buf, idx);
1006         if (sig->generic_param_count)
1007                 sigbuffer_add_value (&buf, sig->generic_param_count);
1008         sigbuffer_add_value (&buf, nparams);
1009         encode_type (assembly, sig->ret, &buf);
1010         for (i = 0; i < nparams; ++i) {
1011                 if (i == sig->sentinelpos)
1012                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1013                 encode_type (assembly, sig->params [i], &buf);
1014         }
1015         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1016         sigbuffer_free (&buf);
1017         return idx;
1018 }
1019 #endif
1020
1021 static guint32
1022 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1023 {
1024         MONO_REQ_GC_UNSAFE_MODE;
1025
1026         mono_error_init (error);
1027
1028         /*
1029          * FIXME: reuse code from method_encode_signature().
1030          */
1031         SigBuffer buf;
1032         int i;
1033         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1034         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1035         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1036         guint32 idx;
1037
1038         sigbuffer_init (&buf, 32);
1039         /* LAMESPEC: all the call conv spec is foobared */
1040         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1041         if (mb->call_conv & 2)
1042                 idx |= 0x5; /* vararg */
1043         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1044                 idx |= 0x20; /* hasthis */
1045         if (ngparams)
1046                 idx |= 0x10; /* generic */
1047         sigbuffer_add_byte (&buf, idx);
1048         if (ngparams)
1049                 sigbuffer_add_value (&buf, ngparams);
1050         sigbuffer_add_value (&buf, nparams + notypes);
1051         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1052         if (!is_ok (error))
1053                 goto leave;
1054         encode_reflection_type (assembly, mb->rtype, &buf, error);
1055         if (!is_ok (error))
1056                 goto leave;
1057         for (i = 0; i < nparams; ++i) {
1058                 MonoArray *modreq = NULL;
1059                 MonoArray *modopt = NULL;
1060                 MonoReflectionType *pt;
1061
1062                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1063                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1064                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1065                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1066                 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1067                 if (!is_ok (error))
1068                         goto leave;
1069                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1070                 encode_reflection_type (assembly, pt, &buf, error);
1071                 if (!is_ok (error))
1072                         goto leave;
1073         }
1074         if (notypes)
1075                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1076         for (i = 0; i < notypes; ++i) {
1077                 MonoReflectionType *pt;
1078
1079                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1080                 encode_reflection_type (assembly, pt, &buf, error);
1081                 if (!is_ok (error))
1082                         goto leave;
1083         }
1084
1085         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1086 leave:
1087         sigbuffer_free (&buf);
1088         return idx;
1089 }
1090
1091 static guint32
1092 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1093 {
1094         MONO_REQ_GC_UNSAFE_MODE;
1095
1096         mono_error_init (error);
1097
1098         MonoDynamicTable *table;
1099         guint32 *values;
1100         guint32 idx, sig_idx;
1101         guint nl = mono_array_length (ilgen->locals);
1102         SigBuffer buf;
1103         int i;
1104
1105         sigbuffer_init (&buf, 32);
1106         sigbuffer_add_value (&buf, 0x07);
1107         sigbuffer_add_value (&buf, nl);
1108         for (i = 0; i < nl; ++i) {
1109                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1110                 
1111                 if (lb->is_pinned)
1112                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1113                 
1114                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1115                 if (!is_ok (error)) {
1116                         sigbuffer_free (&buf);
1117                         return 0;
1118                 }
1119         }
1120         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1121         sigbuffer_free (&buf);
1122
1123         if (assembly->standalonesig_cache == NULL)
1124                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1125         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1126         if (idx)
1127                 return idx;
1128
1129         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1130         idx = table->next_idx ++;
1131         table->rows ++;
1132         alloc_table (table, table->rows);
1133         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1134
1135         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1136
1137         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1138
1139         return idx;
1140 }
1141
1142 static guint32
1143 method_count_clauses (MonoReflectionILGen *ilgen)
1144 {
1145         MONO_REQ_GC_UNSAFE_MODE;
1146
1147         guint32 num_clauses = 0;
1148         int i;
1149
1150         MonoILExceptionInfo *ex_info;
1151         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1152                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1153                 if (ex_info->handlers)
1154                         num_clauses += mono_array_length (ex_info->handlers);
1155                 else
1156                         num_clauses++;
1157         }
1158
1159         return num_clauses;
1160 }
1161
1162 #ifndef DISABLE_REFLECTION_EMIT
1163 static MonoExceptionClause*
1164 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1165 {
1166         MONO_REQ_GC_UNSAFE_MODE;
1167
1168         mono_error_init (error);
1169
1170         MonoExceptionClause *clauses;
1171         MonoExceptionClause *clause;
1172         MonoILExceptionInfo *ex_info;
1173         MonoILExceptionBlock *ex_block;
1174         guint32 finally_start;
1175         int i, j, clause_index;;
1176
1177         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1178
1179         clause_index = 0;
1180         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1181                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1182                 finally_start = ex_info->start + ex_info->len;
1183                 if (!ex_info->handlers)
1184                         continue;
1185                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1186                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1187                         clause = &(clauses [clause_index]);
1188
1189                         clause->flags = ex_block->type;
1190                         clause->try_offset = ex_info->start;
1191
1192                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1193                                 clause->try_len = finally_start - ex_info->start;
1194                         else
1195                                 clause->try_len = ex_info->len;
1196                         clause->handler_offset = ex_block->start;
1197                         clause->handler_len = ex_block->len;
1198                         if (ex_block->extype) {
1199                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1200
1201                                 if (!is_ok (error)) {
1202                                         image_g_free (image, clauses);
1203                                         return NULL;
1204                                 }
1205                                 clause->data.catch_class = mono_class_from_mono_type (extype);
1206                         } else {
1207                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1208                                         clause->data.filter_offset = ex_block->filter_offset;
1209                                 else
1210                                         clause->data.filter_offset = 0;
1211                         }
1212                         finally_start = ex_block->start + ex_block->len;
1213
1214                         clause_index ++;
1215                 }
1216         }
1217
1218         return clauses;
1219 }
1220 #endif /* !DISABLE_REFLECTION_EMIT */
1221
1222 /**
1223  * method_encode_code:
1224  *
1225  * @assembly the assembly
1226  * @mb the managed MethodBuilder
1227  * @error set on error
1228  *
1229  * Note that the return value is not sensible if @error is set.
1230  */
1231 static guint32
1232 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1233 {
1234         MONO_REQ_GC_UNSAFE_MODE;
1235
1236         char flags = 0;
1237         guint32 idx;
1238         guint32 code_size;
1239         gint32 max_stack, i;
1240         gint32 num_locals = 0;
1241         gint32 num_exception = 0;
1242         gint maybe_small;
1243         guint32 fat_flags;
1244         char fat_header [12];
1245         guint32 int_value;
1246         guint16 short_value;
1247         guint32 local_sig = 0;
1248         guint32 header_size = 12;
1249         MonoArray *code;
1250
1251         mono_error_init (error);
1252
1253         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1254                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1255                 return 0;
1256
1257         /*if (mb->name)
1258                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1259         if (mb->ilgen) {
1260                 code = mb->ilgen->code;
1261                 code_size = mb->ilgen->code_len;
1262                 max_stack = mb->ilgen->max_stack;
1263                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1264                 if (mb->ilgen->ex_handlers)
1265                         num_exception = method_count_clauses (mb->ilgen);
1266         } else {
1267                 code = mb->code;
1268                 if (code == NULL){
1269                         MonoError inner_error;
1270                         char *name = mono_string_to_utf8_checked (mb->name, &inner_error);
1271                         if (!is_ok (&inner_error)) {
1272                                 name = g_strdup ("");
1273                                 mono_error_cleanup (&inner_error);
1274                         }
1275                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1276                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1277                         g_free (str);
1278                         g_free (name);
1279                         return 0;
1280                 }
1281
1282                 code_size = mono_array_length (code);
1283                 max_stack = 8; /* we probably need to run a verifier on the code... */
1284         }
1285
1286         stream_data_align (&assembly->code);
1287
1288         /* check for exceptions, maxstack, locals */
1289         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1290         if (maybe_small) {
1291                 if (code_size < 64 && !(code_size & 1)) {
1292                         flags = (code_size << 2) | 0x2;
1293                 } else if (code_size < 32 && (code_size & 1)) {
1294                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1295                 } else {
1296                         goto fat_header;
1297                 }
1298                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1299                 /* add to the fixup todo list */
1300                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1301                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1302                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1303                 return assembly->text_rva + idx;
1304         } 
1305 fat_header:
1306         if (num_locals) {
1307                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1308                 return_val_if_nok (error, 0);
1309         }
1310         /* 
1311          * FIXME: need to set also the header size in fat_flags.
1312          * (and more sects and init locals flags)
1313          */
1314         fat_flags =  0x03;
1315         if (num_exception)
1316                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1317         if (mb->init_locals)
1318                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1319         fat_header [0] = fat_flags;
1320         fat_header [1] = (header_size / 4 ) << 4;
1321         short_value = GUINT16_TO_LE (max_stack);
1322         memcpy (fat_header + 2, &short_value, 2);
1323         int_value = GUINT32_TO_LE (code_size);
1324         memcpy (fat_header + 4, &int_value, 4);
1325         int_value = GUINT32_TO_LE (local_sig);
1326         memcpy (fat_header + 8, &int_value, 4);
1327         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1328         /* add to the fixup todo list */
1329         if (mb->ilgen && mb->ilgen->num_token_fixups)
1330                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1331         
1332         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1333         if (num_exception) {
1334                 unsigned char sheader [4];
1335                 MonoILExceptionInfo * ex_info;
1336                 MonoILExceptionBlock * ex_block;
1337                 int j;
1338
1339                 stream_data_align (&assembly->code);
1340                 /* always use fat format for now */
1341                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1342                 num_exception *= 6 * sizeof (guint32);
1343                 num_exception += 4; /* include the size of the header */
1344                 sheader [1] = num_exception & 0xff;
1345                 sheader [2] = (num_exception >> 8) & 0xff;
1346                 sheader [3] = (num_exception >> 16) & 0xff;
1347                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1348                 /* fat header, so we are already aligned */
1349                 /* reverse order */
1350                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1351                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1352                         if (ex_info->handlers) {
1353                                 int finally_start = ex_info->start + ex_info->len;
1354                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1355                                         guint32 val;
1356                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1357                                         /* the flags */
1358                                         val = GUINT32_TO_LE (ex_block->type);
1359                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1360                                         /* try offset */
1361                                         val = GUINT32_TO_LE (ex_info->start);
1362                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1363                                         /* need fault, too, probably */
1364                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1365                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1366                                         else
1367                                                 val = GUINT32_TO_LE (ex_info->len);
1368                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1369                                         /* handler offset */
1370                                         val = GUINT32_TO_LE (ex_block->start);
1371                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1372                                         /* handler len */
1373                                         val = GUINT32_TO_LE (ex_block->len);
1374                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1375                                         finally_start = ex_block->start + ex_block->len;
1376                                         if (ex_block->extype) {
1377                                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1378                                                 return_val_if_nok (error, 0);
1379
1380                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1381                                         } else {
1382                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1383                                                         val = ex_block->filter_offset;
1384                                                 else
1385                                                         val = 0;
1386                                         }
1387                                         val = GUINT32_TO_LE (val);
1388                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1389                                         /*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", 
1390                                                         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);*/
1391                                 }
1392                         } else {
1393                                 g_error ("No clauses for ex info block %d", i);
1394                         }
1395                 }
1396         }
1397         return assembly->text_rva + idx;
1398 }
1399
1400 static guint32
1401 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1402 {
1403         MONO_REQ_GC_NEUTRAL_MODE;
1404
1405         int i;
1406         MonoDynamicTable *table;
1407         guint32 *values;
1408         
1409         table = &assembly->tables [table_idx];
1410
1411         g_assert (col < table->columns);
1412
1413         values = table->values + table->columns;
1414         for (i = 1; i <= table->rows; ++i) {
1415                 if (values [col] == token)
1416                         return i;
1417                 values += table->columns;
1418         }
1419         return 0;
1420 }
1421
1422 /*
1423  * LOCKING: Acquires the loader lock. 
1424  */
1425 static MonoCustomAttrInfo*
1426 lookup_custom_attr (MonoImage *image, gpointer member)
1427 {
1428         MONO_REQ_GC_NEUTRAL_MODE;
1429
1430         MonoCustomAttrInfo* res;
1431
1432         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1433
1434         if (!res)
1435                 return NULL;
1436
1437         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1438         res->cached = 0;
1439         return res;
1440 }
1441
1442 static gboolean
1443 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1444 {
1445         MONO_REQ_GC_UNSAFE_MODE;
1446
1447         /* FIXME: Need to do more checks */
1448         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1449                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1450
1451                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1452                         return FALSE;
1453         }
1454
1455         return TRUE;
1456 }
1457
1458 static MonoCustomAttrInfo*
1459 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1460 {
1461         MONO_REQ_GC_UNSAFE_MODE;
1462
1463         int i, index, count, not_visible;
1464         MonoCustomAttrInfo *ainfo;
1465         MonoReflectionCustomAttr *cattr;
1466
1467         if (!cattrs)
1468                 return NULL;
1469         /* FIXME: check in assembly the Run flag is set */
1470
1471         count = mono_array_length (cattrs);
1472
1473         /* Skip nonpublic attributes since MS.NET seems to do the same */
1474         /* FIXME: This needs to be done more globally */
1475         not_visible = 0;
1476         for (i = 0; i < count; ++i) {
1477                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1478                 if (!custom_attr_visible (image, cattr))
1479                         not_visible ++;
1480         }
1481
1482         int num_attrs = count - not_visible;
1483         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * num_attrs);
1484
1485         ainfo->image = image;
1486         ainfo->num_attrs = num_attrs;
1487         ainfo->cached = alloc_img != NULL;
1488         index = 0;
1489         for (i = 0; i < count; ++i) {
1490                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1491                 if (custom_attr_visible (image, cattr)) {
1492                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1493                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1494                         ainfo->attrs [index].ctor = cattr->ctor->method;
1495                         g_assert (cattr->ctor->method);
1496                         ainfo->attrs [index].data = saved;
1497                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1498                         index ++;
1499                 }
1500         }
1501         g_assert (index == num_attrs && count == num_attrs + not_visible);
1502
1503         return ainfo;
1504 }
1505
1506 #ifndef DISABLE_REFLECTION_EMIT
1507 /*
1508  * LOCKING: Acquires the loader lock. 
1509  */
1510 static void
1511 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1512 {
1513         MONO_REQ_GC_UNSAFE_MODE;
1514
1515         MonoCustomAttrInfo *ainfo, *tmp;
1516
1517         if (!cattrs || !mono_array_length (cattrs))
1518                 return;
1519
1520         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1521
1522         mono_loader_lock ();
1523         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1524         if (tmp)
1525                 mono_custom_attrs_free (tmp);
1526         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1527         mono_loader_unlock ();
1528
1529 }
1530 #endif
1531
1532 void
1533 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1534 {
1535         MONO_REQ_GC_NEUTRAL_MODE;
1536
1537         if (ainfo && !ainfo->cached)
1538                 g_free (ainfo);
1539 }
1540
1541 /*
1542  * idx is the table index of the object
1543  * type is one of MONO_CUSTOM_ATTR_*
1544  */
1545 static gboolean
1546 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1547 {
1548         MONO_REQ_GC_UNSAFE_MODE;
1549
1550         MonoDynamicTable *table;
1551         MonoReflectionCustomAttr *cattr;
1552         guint32 *values;
1553         guint32 count, i, token;
1554         char blob_size [6];
1555         char *p = blob_size;
1556         
1557         mono_error_init (error);
1558
1559         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1560         if (!cattrs)
1561                 return TRUE;
1562         count = mono_array_length (cattrs);
1563         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1564         table->rows += count;
1565         alloc_table (table, table->rows);
1566         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1567         idx <<= MONO_CUSTOM_ATTR_BITS;
1568         idx |= type;
1569         for (i = 0; i < count; ++i) {
1570                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1571                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1572                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1573                 if (!mono_error_ok (error)) goto fail;
1574                 type = mono_metadata_token_index (token);
1575                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1576                 switch (mono_metadata_token_table (token)) {
1577                 case MONO_TABLE_METHOD:
1578                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1579                         /*
1580                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1581                          * method, not the one returned by mono_image_create_token ().
1582                          */
1583                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1584                         break;
1585                 case MONO_TABLE_MEMBERREF:
1586                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1587                         break;
1588                 default:
1589                         g_warning ("got wrong token in custom attr");
1590                         continue;
1591                 }
1592                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1593                 p = blob_size;
1594                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1595                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1596                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1597                 values += MONO_CUSTOM_ATTR_SIZE;
1598                 ++table->next_idx;
1599         }
1600
1601         return TRUE;
1602
1603 fail:
1604         return FALSE;
1605 }
1606
1607 static void
1608 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1609 {
1610         MONO_REQ_GC_UNSAFE_MODE;
1611
1612         MonoDynamicTable *table;
1613         guint32 *values;
1614         guint32 count, i, idx;
1615         MonoReflectionPermissionSet *perm;
1616
1617         if (!permissions)
1618                 return;
1619
1620         count = mono_array_length (permissions);
1621         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1622         table->rows += count;
1623         alloc_table (table, table->rows);
1624
1625         for (i = 0; i < mono_array_length (permissions); ++i) {
1626                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1627
1628                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1629
1630                 idx = mono_metadata_token_index (parent_token);
1631                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1632                 switch (mono_metadata_token_table (parent_token)) {
1633                 case MONO_TABLE_TYPEDEF:
1634                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1635                         break;
1636                 case MONO_TABLE_METHOD:
1637                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1638                         break;
1639                 case MONO_TABLE_ASSEMBLY:
1640                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1641                         break;
1642                 default:
1643                         g_assert_not_reached ();
1644                 }
1645
1646                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1647                 values [MONO_DECL_SECURITY_PARENT] = idx;
1648                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1649
1650                 ++table->next_idx;
1651         }
1652 }
1653
1654 /*
1655  * Fill in the MethodDef and ParamDef tables for a method.
1656  * This is used for both normal methods and constructors.
1657  */
1658 static gboolean
1659 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1660 {
1661         MONO_REQ_GC_UNSAFE_MODE;
1662
1663         MonoDynamicTable *table;
1664         guint32 *values;
1665         guint i, count;
1666
1667         mono_error_init (error);
1668
1669         /* room in this table is already allocated */
1670         table = &assembly->tables [MONO_TABLE_METHOD];
1671         *mb->table_idx = table->next_idx ++;
1672         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1673         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1674         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
1675         return_val_if_nok (error, FALSE);
1676         values [MONO_METHOD_FLAGS] = mb->attrs;
1677         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1678         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1679         return_val_if_nok (error, FALSE);
1680         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1681         return_val_if_nok (error, FALSE);
1682
1683         table = &assembly->tables [MONO_TABLE_PARAM];
1684         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1685
1686         mono_image_add_decl_security (assembly, 
1687                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1688
1689         if (mb->pinfo) {
1690                 MonoDynamicTable *mtable;
1691                 guint32 *mvalues;
1692                 
1693                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1694                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1695                 
1696                 count = 0;
1697                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1698                         if (mono_array_get (mb->pinfo, gpointer, i))
1699                                 count++;
1700                 }
1701                 table->rows += count;
1702                 alloc_table (table, table->rows);
1703                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1704                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1705                         MonoReflectionParamBuilder *pb;
1706                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1707                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1708                                 values [MONO_PARAM_SEQUENCE] = i;
1709                                 if (pb->name != NULL) {
1710                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
1711                                         return_val_if_nok (error, FALSE);
1712                                 } else {
1713                                         values [MONO_PARAM_NAME] = 0;
1714                                 }
1715                                 values += MONO_PARAM_SIZE;
1716                                 if (pb->marshal_info) {
1717                                         mtable->rows++;
1718                                         alloc_table (mtable, mtable->rows);
1719                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1720                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1721                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1722                                         return_val_if_nok (error, FALSE);
1723                                 }
1724                                 pb->table_idx = table->next_idx++;
1725                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1726                                         guint32 field_type = 0;
1727                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1728                                         mtable->rows ++;
1729                                         alloc_table (mtable, mtable->rows);
1730                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1731                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1732                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1733                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1734                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1735                                 }
1736                         }
1737                 }
1738         }
1739
1740         return TRUE;
1741 }
1742
1743 #ifndef DISABLE_REFLECTION_EMIT
1744 static gboolean
1745 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1746 {
1747         MONO_REQ_GC_UNSAFE_MODE;
1748
1749         mono_error_init (error);
1750         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1751
1752         rmb->ilgen = mb->ilgen;
1753         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1754         return_val_if_nok (error, FALSE);
1755         rmb->parameters = mb->parameters;
1756         rmb->generic_params = mb->generic_params;
1757         rmb->generic_container = mb->generic_container;
1758         rmb->opt_types = NULL;
1759         rmb->pinfo = mb->pinfo;
1760         rmb->attrs = mb->attrs;
1761         rmb->iattrs = mb->iattrs;
1762         rmb->call_conv = mb->call_conv;
1763         rmb->code = mb->code;
1764         rmb->type = mb->type;
1765         rmb->name = mb->name;
1766         rmb->table_idx = &mb->table_idx;
1767         rmb->init_locals = mb->init_locals;
1768         rmb->skip_visibility = FALSE;
1769         rmb->return_modreq = mb->return_modreq;
1770         rmb->return_modopt = mb->return_modopt;
1771         rmb->param_modreq = mb->param_modreq;
1772         rmb->param_modopt = mb->param_modopt;
1773         rmb->permissions = mb->permissions;
1774         rmb->mhandle = mb->mhandle;
1775         rmb->nrefs = 0;
1776         rmb->refs = NULL;
1777
1778         if (mb->dll) {
1779                 rmb->charset = mb->charset;
1780                 rmb->extra_flags = mb->extra_flags;
1781                 rmb->native_cc = mb->native_cc;
1782                 rmb->dllentry = mb->dllentry;
1783                 rmb->dll = mb->dll;
1784         }
1785
1786         return TRUE;
1787 }
1788
1789 static gboolean
1790 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1791 {
1792         MONO_REQ_GC_UNSAFE_MODE;
1793
1794         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1795
1796         mono_error_init (error);
1797
1798         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1799
1800         rmb->ilgen = mb->ilgen;
1801         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1802         return_val_if_nok (error, FALSE);
1803         rmb->parameters = mb->parameters;
1804         rmb->generic_params = NULL;
1805         rmb->generic_container = NULL;
1806         rmb->opt_types = NULL;
1807         rmb->pinfo = mb->pinfo;
1808         rmb->attrs = mb->attrs;
1809         rmb->iattrs = mb->iattrs;
1810         rmb->call_conv = mb->call_conv;
1811         rmb->code = NULL;
1812         rmb->type = mb->type;
1813         rmb->name = mono_string_new (mono_domain_get (), name);
1814         rmb->table_idx = &mb->table_idx;
1815         rmb->init_locals = mb->init_locals;
1816         rmb->skip_visibility = FALSE;
1817         rmb->return_modreq = NULL;
1818         rmb->return_modopt = NULL;
1819         rmb->param_modreq = mb->param_modreq;
1820         rmb->param_modopt = mb->param_modopt;
1821         rmb->permissions = mb->permissions;
1822         rmb->mhandle = mb->mhandle;
1823         rmb->nrefs = 0;
1824         rmb->refs = NULL;
1825
1826         return TRUE;
1827 }
1828
1829 static void
1830 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1831 {
1832         MONO_REQ_GC_UNSAFE_MODE;
1833
1834         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1835
1836         rmb->ilgen = mb->ilgen;
1837         rmb->rtype = mb->rtype;
1838         rmb->parameters = mb->parameters;
1839         rmb->generic_params = NULL;
1840         rmb->generic_container = NULL;
1841         rmb->opt_types = NULL;
1842         rmb->pinfo = NULL;
1843         rmb->attrs = mb->attrs;
1844         rmb->iattrs = 0;
1845         rmb->call_conv = mb->call_conv;
1846         rmb->code = NULL;
1847         rmb->type = (MonoObject *) mb->owner;
1848         rmb->name = mb->name;
1849         rmb->table_idx = NULL;
1850         rmb->init_locals = mb->init_locals;
1851         rmb->skip_visibility = mb->skip_visibility;
1852         rmb->return_modreq = NULL;
1853         rmb->return_modopt = NULL;
1854         rmb->param_modreq = NULL;
1855         rmb->param_modopt = NULL;
1856         rmb->permissions = NULL;
1857         rmb->mhandle = mb->mhandle;
1858         rmb->nrefs = 0;
1859         rmb->refs = NULL;
1860 }       
1861 #endif
1862
1863 static gboolean
1864 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1865 {
1866         MONO_REQ_GC_UNSAFE_MODE;
1867
1868         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1869         MonoDynamicTable *table;
1870         guint32 *values;
1871         guint32 tok;
1872         MonoReflectionMethod *m;
1873         int i;
1874
1875         mono_error_init (error);
1876
1877         if (!mb->override_methods)
1878                 return TRUE;
1879
1880         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1881                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1882
1883                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1884                 table->rows ++;
1885                 alloc_table (table, table->rows);
1886                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1887                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1888                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1889
1890                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1891                 return_val_if_nok (error, FALSE);
1892
1893                 switch (mono_metadata_token_table (tok)) {
1894                 case MONO_TABLE_MEMBERREF:
1895                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1896                         break;
1897                 case MONO_TABLE_METHOD:
1898                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1899                         break;
1900                 default:
1901                         g_assert_not_reached ();
1902                 }
1903                 values [MONO_METHODIMPL_DECLARATION] = tok;
1904         }
1905
1906         return TRUE;
1907 }
1908
1909 #ifndef DISABLE_REFLECTION_EMIT
1910 static gboolean
1911 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1912 {
1913         MONO_REQ_GC_UNSAFE_MODE;
1914
1915         MonoDynamicTable *table;
1916         guint32 *values;
1917         ReflectionMethodBuilder rmb;
1918         int i;
1919
1920         mono_error_init (error);
1921
1922         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1923             !mono_image_basic_method (&rmb, assembly, error))
1924                 return FALSE;
1925
1926         mb->table_idx = *rmb.table_idx;
1927
1928         if (mb->dll) { /* It's a P/Invoke method */
1929                 guint32 moduleref;
1930                 /* map CharSet values to on-disk values */
1931                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1932                 int extra_flags = mb->extra_flags;
1933                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1934                 table->rows ++;
1935                 alloc_table (table, table->rows);
1936                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1937                 
1938                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1939                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1940                 if (mb->dllentry) {
1941                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry, error);
1942                         return_val_if_nok (error, FALSE);
1943                 } else {
1944                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
1945                         return_val_if_nok (error, FALSE);
1946                 }
1947                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll, error);
1948                 return_val_if_nok (error, FALSE);
1949                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1950                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1951                         table->rows ++;
1952                         alloc_table (table, table->rows);
1953                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1954                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1955                 }
1956         }
1957
1958         if (mb->generic_params) {
1959                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1960                 table->rows += mono_array_length (mb->generic_params);
1961                 alloc_table (table, table->rows);
1962                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1963                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1964
1965                         mono_image_get_generic_param_info (
1966                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1967                 }
1968         }
1969
1970         return TRUE;
1971 }
1972
1973 static gboolean
1974 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1975 {
1976         MONO_REQ_GC_UNSAFE_MODE;
1977
1978         ReflectionMethodBuilder rmb;
1979
1980         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1981                 return FALSE;
1982
1983         if (!mono_image_basic_method (&rmb, assembly, error))
1984                 return FALSE;
1985
1986         mb->table_idx = *rmb.table_idx;
1987
1988         return TRUE;
1989 }
1990 #endif
1991
1992 static char*
1993 type_get_fully_qualified_name (MonoType *type)
1994 {
1995         MONO_REQ_GC_NEUTRAL_MODE;
1996
1997         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1998 }
1999
2000 static char*
2001 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
2002 {
2003         MONO_REQ_GC_UNSAFE_MODE;
2004
2005         MonoClass *klass;
2006         MonoAssembly *ta;
2007
2008         klass = mono_class_from_mono_type (type);
2009         if (!klass) 
2010                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2011         ta = klass->image->assembly;
2012         if (assembly_is_dynamic (ta) || (ta == ass)) {
2013                 if (klass->generic_class || klass->generic_container)
2014                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
2015                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2016                 else
2017                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2018         }
2019
2020         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2021 }
2022
2023 #ifndef DISABLE_REFLECTION_EMIT
2024 /*field_image is the image to which the eventual custom mods have been encoded against*/
2025 static guint32
2026 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2027 {
2028         MONO_REQ_GC_NEUTRAL_MODE;
2029
2030         SigBuffer buf;
2031         guint32 idx, i, token;
2032
2033         if (!assembly->save)
2034                 return 0;
2035
2036         sigbuffer_init (&buf, 32);
2037         
2038         sigbuffer_add_value (&buf, 0x06);
2039         /* encode custom attributes before the type */
2040         if (type->num_mods) {
2041                 for (i = 0; i < type->num_mods; ++i) {
2042                         if (field_image) {
2043                                 MonoError error;
2044                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2045                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2046
2047                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2048                         } else {
2049                                 token = type->modifiers [i].token;
2050                         }
2051
2052                         if (type->modifiers [i].required)
2053                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2054                         else
2055                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2056
2057                         sigbuffer_add_value (&buf, token);
2058                 }
2059         }
2060         encode_type (assembly, type, &buf);
2061         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2062         sigbuffer_free (&buf);
2063         return idx;
2064 }
2065 #endif
2066
2067 static guint32
2068 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2069 {
2070         MONO_REQ_GC_UNSAFE_MODE;
2071
2072         mono_error_init (error);
2073
2074         SigBuffer buf;
2075         guint32 idx;
2076         guint32 typespec = 0;
2077         MonoType *type;
2078         MonoClass *klass;
2079
2080         init_type_builder_generics (fb->type, error);
2081         return_val_if_nok (error, 0);
2082
2083         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2084         return_val_if_nok (error, 0);
2085         klass = mono_class_from_mono_type (type);
2086
2087         sigbuffer_init (&buf, 32);
2088         
2089         sigbuffer_add_value (&buf, 0x06);
2090         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2091         if (!is_ok (error))
2092                 goto fail;
2093         /* encode custom attributes before the type */
2094
2095         if (klass->generic_container)
2096                 typespec = create_typespec (assembly, type);
2097
2098         if (typespec) {
2099                 MonoGenericClass *gclass;
2100                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2101                 encode_generic_class (assembly, gclass, &buf);
2102         } else {
2103                 encode_type (assembly, type, &buf);
2104         }
2105         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2106         sigbuffer_free (&buf);
2107         return idx;
2108 fail:
2109         sigbuffer_free (&buf);
2110         return 0;
2111 }
2112
2113 static guint32
2114 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2115 {
2116         MONO_REQ_GC_UNSAFE_MODE;
2117
2118         char blob_size [64];
2119         char *b = blob_size;
2120         char *box_val;
2121         char* buf;
2122         guint32 idx = 0, len = 0, dummy = 0;
2123
2124         buf = (char *)g_malloc (64);
2125         if (!val) {
2126                 *ret_type = MONO_TYPE_CLASS;
2127                 len = 4;
2128                 box_val = (char*)&dummy;
2129         } else {
2130                 box_val = ((char*)val) + sizeof (MonoObject);
2131                 *ret_type = val->vtable->klass->byval_arg.type;
2132         }
2133 handle_enum:
2134         switch (*ret_type) {
2135         case MONO_TYPE_BOOLEAN:
2136         case MONO_TYPE_U1:
2137         case MONO_TYPE_I1:
2138                 len = 1;
2139                 break;
2140         case MONO_TYPE_CHAR:
2141         case MONO_TYPE_U2:
2142         case MONO_TYPE_I2:
2143                 len = 2;
2144                 break;
2145         case MONO_TYPE_U4:
2146         case MONO_TYPE_I4:
2147         case MONO_TYPE_R4:
2148                 len = 4;
2149                 break;
2150         case MONO_TYPE_U8:
2151         case MONO_TYPE_I8:
2152                 len = 8;
2153                 break;
2154         case MONO_TYPE_R8:
2155                 len = 8;
2156                 break;
2157         case MONO_TYPE_VALUETYPE: {
2158                 MonoClass *klass = val->vtable->klass;
2159                 
2160                 if (klass->enumtype) {
2161                         *ret_type = mono_class_enum_basetype (klass)->type;
2162                         goto handle_enum;
2163                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2164                         len = 8;
2165                 } else 
2166                         g_error ("we can't encode valuetypes, we should have never reached this line");
2167                 break;
2168         }
2169         case MONO_TYPE_CLASS:
2170                 break;
2171         case MONO_TYPE_STRING: {
2172                 MonoString *str = (MonoString*)val;
2173                 /* there is no signature */
2174                 len = str->length * 2;
2175                 mono_metadata_encode_value (len, b, &b);
2176 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2177                 {
2178                         char *swapped = g_malloc (2 * mono_string_length (str));
2179                         const char *p = (const char*)mono_string_chars (str);
2180
2181                         swap_with_size (swapped, p, 2, mono_string_length (str));
2182                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2183                         g_free (swapped);
2184                 }
2185 #else
2186                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2187 #endif
2188
2189                 g_free (buf);
2190                 return idx;
2191         }
2192         case MONO_TYPE_GENERICINST:
2193                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2194                 goto handle_enum;
2195         default:
2196                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2197         }
2198
2199         /* there is no signature */
2200         mono_metadata_encode_value (len, b, &b);
2201 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2202         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2203         swap_with_size (blob_size, box_val, len, 1);
2204         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2205 #else
2206         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2207 #endif
2208
2209         g_free (buf);
2210         return idx;
2211 }
2212
2213 static guint32
2214 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2215 {
2216         MONO_REQ_GC_UNSAFE_MODE;
2217
2218         mono_error_init (error);
2219
2220         char *str;
2221         SigBuffer buf;
2222         guint32 idx, len;
2223
2224         sigbuffer_init (&buf, 32);
2225
2226         sigbuffer_add_value (&buf, minfo->type);
2227
2228         switch (minfo->type) {
2229         case MONO_NATIVE_BYVALTSTR:
2230         case MONO_NATIVE_BYVALARRAY:
2231                 sigbuffer_add_value (&buf, minfo->count);
2232                 break;
2233         case MONO_NATIVE_LPARRAY:
2234                 if (minfo->eltype || minfo->has_size) {
2235                         sigbuffer_add_value (&buf, minfo->eltype);
2236                         if (minfo->has_size) {
2237                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2238                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2239
2240                                 /* LAMESPEC: ElemMult is undocumented */
2241                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2242                         }
2243                 }
2244                 break;
2245         case MONO_NATIVE_SAFEARRAY:
2246                 if (minfo->eltype)
2247                         sigbuffer_add_value (&buf, minfo->eltype);
2248                 break;
2249         case MONO_NATIVE_CUSTOM:
2250                 if (minfo->guid) {
2251                         str = mono_string_to_utf8_checked (minfo->guid, error);
2252                         if (!is_ok (error)) {
2253                                 sigbuffer_free (&buf);
2254                                 return 0;
2255                         }
2256                         len = strlen (str);
2257                         sigbuffer_add_value (&buf, len);
2258                         sigbuffer_add_mem (&buf, str, len);
2259                         g_free (str);
2260                 } else {
2261                         sigbuffer_add_value (&buf, 0);
2262                 }
2263                 /* native type name */
2264                 sigbuffer_add_value (&buf, 0);
2265                 /* custom marshaler type name */
2266                 if (minfo->marshaltype || minfo->marshaltyperef) {
2267                         if (minfo->marshaltyperef) {
2268                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2269                                 if (!is_ok (error)) {
2270                                         sigbuffer_free (&buf);
2271                                         return 0;
2272                                 }
2273                                 str = type_get_fully_qualified_name (marshaltype);
2274                         } else {
2275                                 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
2276                                 if (!is_ok (error)) {
2277                                         sigbuffer_free (&buf);
2278                                         return 0;
2279                                 }
2280                         }
2281                         len = strlen (str);
2282                         sigbuffer_add_value (&buf, len);
2283                         sigbuffer_add_mem (&buf, str, len);
2284                         g_free (str);
2285                 } else {
2286                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2287                         sigbuffer_add_value (&buf, 0);
2288                 }
2289                 if (minfo->mcookie) {
2290                         str = mono_string_to_utf8_checked (minfo->mcookie, error);
2291                         if (!is_ok (error)) {
2292                                 sigbuffer_free (&buf);
2293                                 return 0;
2294                         }
2295                         len = strlen (str);
2296                         sigbuffer_add_value (&buf, len);
2297                         sigbuffer_add_mem (&buf, str, len);
2298                         g_free (str);
2299                 } else {
2300                         sigbuffer_add_value (&buf, 0);
2301                 }
2302                 break;
2303         default:
2304                 break;
2305         }
2306         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2307         sigbuffer_free (&buf);
2308         return idx;
2309 }
2310
2311 static void
2312 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2313 {
2314         MONO_REQ_GC_UNSAFE_MODE;
2315
2316         mono_error_init (error);
2317
2318         MonoDynamicTable *table;
2319         guint32 *values;
2320
2321         /* maybe this fixup should be done in the C# code */
2322         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2323                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2324         table = &assembly->tables [MONO_TABLE_FIELD];
2325         fb->table_idx = table->next_idx ++;
2326         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2327         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2328         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name, error);
2329         return_if_nok (error);
2330         values [MONO_FIELD_FLAGS] = fb->attrs;
2331         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2332         return_if_nok (error);
2333
2334
2335         if (fb->offset != -1) {
2336                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2337                 table->rows ++;
2338                 alloc_table (table, table->rows);
2339                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2340                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2341                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2342         }
2343         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2344                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2345                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2346                 table->rows ++;
2347                 alloc_table (table, table->rows);
2348                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2349                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2350                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2351                 values [MONO_CONSTANT_TYPE] = field_type;
2352                 values [MONO_CONSTANT_PADDING] = 0;
2353         }
2354         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2355                 guint32 rva_idx;
2356                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2357                 table->rows ++;
2358                 alloc_table (table, table->rows);
2359                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2360                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2361                 /*
2362                  * We store it in the code section because it's simpler for now.
2363                  */
2364                 if (fb->rva_data) {
2365                         if (mono_array_length (fb->rva_data) >= 10)
2366                                 stream_data_align (&assembly->code);
2367                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2368                 } else
2369                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2370                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2371         }
2372         if (fb->marshal_info) {
2373                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2374                 table->rows ++;
2375                 alloc_table (table, table->rows);
2376                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2377                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2378                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2379                 return_if_nok (error);
2380         }
2381 }
2382
2383 static guint32
2384 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2385 {
2386         MONO_REQ_GC_UNSAFE_MODE;
2387
2388         mono_error_init (error);
2389
2390         SigBuffer buf;
2391         guint32 nparams = 0;
2392         MonoReflectionMethodBuilder *mb = fb->get_method;
2393         MonoReflectionMethodBuilder *smb = fb->set_method;
2394         guint32 idx, i;
2395
2396         if (mb && mb->parameters)
2397                 nparams = mono_array_length (mb->parameters);
2398         if (!mb && smb && smb->parameters)
2399                 nparams = mono_array_length (smb->parameters) - 1;
2400         sigbuffer_init (&buf, 32);
2401         if (fb->call_conv & 0x20)
2402                 sigbuffer_add_byte (&buf, 0x28);
2403         else
2404                 sigbuffer_add_byte (&buf, 0x08);
2405         sigbuffer_add_value (&buf, nparams);
2406         if (mb) {
2407                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2408                 if (!is_ok (error))
2409                         goto fail;
2410                 for (i = 0; i < nparams; ++i) {
2411                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2412                         encode_reflection_type (assembly, pt, &buf, error);
2413                         if (!is_ok (error))
2414                                 goto fail;
2415                 }
2416         } else if (smb && smb->parameters) {
2417                 /* the property type is the last param */
2418                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2419                 if (!is_ok (error))
2420                         goto fail;
2421
2422                 for (i = 0; i < nparams; ++i) {
2423                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2424                         encode_reflection_type (assembly, pt, &buf, error);
2425                         if (!is_ok (error))
2426                                 goto fail;
2427                 }
2428         } else {
2429                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2430                 if (!is_ok (error))
2431                         goto fail;
2432         }
2433
2434         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2435         sigbuffer_free (&buf);
2436         return idx;
2437 fail:
2438         sigbuffer_free (&buf);
2439         return 0;
2440 }
2441
2442 static void
2443 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2444 {
2445         MONO_REQ_GC_UNSAFE_MODE;
2446
2447         mono_error_init (error);
2448
2449         MonoDynamicTable *table;
2450         guint32 *values;
2451         guint num_methods = 0;
2452         guint32 semaidx;
2453
2454         /* 
2455          * we need to set things in the following tables:
2456          * PROPERTYMAP (info already filled in _get_type_info ())
2457          * PROPERTY    (rows already preallocated in _get_type_info ())
2458          * METHOD      (method info already done with the generic method code)
2459          * METHODSEMANTICS
2460          * CONSTANT
2461          */
2462         table = &assembly->tables [MONO_TABLE_PROPERTY];
2463         pb->table_idx = table->next_idx ++;
2464         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2465         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
2466         return_if_nok (error);
2467         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2468         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2469         return_if_nok (error);
2470
2471
2472         /* FIXME: we still don't handle 'other' methods */
2473         if (pb->get_method) num_methods ++;
2474         if (pb->set_method) num_methods ++;
2475
2476         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2477         table->rows += num_methods;
2478         alloc_table (table, table->rows);
2479
2480         if (pb->get_method) {
2481                 semaidx = table->next_idx ++;
2482                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2483                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2484                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2485                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2486         }
2487         if (pb->set_method) {
2488                 semaidx = table->next_idx ++;
2489                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2490                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2491                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2492                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2493         }
2494         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2495                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2496                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2497                 table->rows ++;
2498                 alloc_table (table, table->rows);
2499                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2500                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2501                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2502                 values [MONO_CONSTANT_TYPE] = field_type;
2503                 values [MONO_CONSTANT_PADDING] = 0;
2504         }
2505 }
2506
2507 static void
2508 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2509 {
2510         MONO_REQ_GC_UNSAFE_MODE;
2511
2512         MonoDynamicTable *table;
2513         guint32 *values;
2514         guint num_methods = 0;
2515         guint32 semaidx;
2516
2517         /* 
2518          * we need to set things in the following tables:
2519          * EVENTMAP (info already filled in _get_type_info ())
2520          * EVENT    (rows already preallocated in _get_type_info ())
2521          * METHOD      (method info already done with the generic method code)
2522          * METHODSEMANTICS
2523          */
2524         table = &assembly->tables [MONO_TABLE_EVENT];
2525         eb->table_idx = table->next_idx ++;
2526         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2527         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name, error);
2528         return_if_nok (error);
2529         values [MONO_EVENT_FLAGS] = eb->attrs;
2530         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2531         return_if_nok (error);
2532         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2533
2534         /*
2535          * FIXME: we still don't handle 'other' methods 
2536          */
2537         if (eb->add_method) num_methods ++;
2538         if (eb->remove_method) num_methods ++;
2539         if (eb->raise_method) num_methods ++;
2540
2541         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2542         table->rows += num_methods;
2543         alloc_table (table, table->rows);
2544
2545         if (eb->add_method) {
2546                 semaidx = table->next_idx ++;
2547                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2548                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2549                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2550                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2551         }
2552         if (eb->remove_method) {
2553                 semaidx = table->next_idx ++;
2554                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2555                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2556                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2557                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2558         }
2559         if (eb->raise_method) {
2560                 semaidx = table->next_idx ++;
2561                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2562                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2563                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2564                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2565         }
2566 }
2567
2568 static void
2569 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2570 {
2571         MONO_REQ_GC_UNSAFE_MODE;
2572
2573         mono_error_init (error);
2574
2575         MonoDynamicTable *table;
2576         guint32 num_constraints, i;
2577         guint32 *values;
2578         guint32 table_idx;
2579
2580         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2581         num_constraints = gparam->iface_constraints ?
2582                 mono_array_length (gparam->iface_constraints) : 0;
2583         table->rows += num_constraints;
2584         if (gparam->base_type)
2585                 table->rows++;
2586         alloc_table (table, table->rows);
2587
2588         if (gparam->base_type) {
2589                 table_idx = table->next_idx ++;
2590                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2591
2592                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2593                 return_if_nok (error);
2594                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2595                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2596         }
2597
2598         for (i = 0; i < num_constraints; i++) {
2599                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2600                         gparam->iface_constraints, gpointer, i);
2601
2602                 table_idx = table->next_idx ++;
2603                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2604
2605                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2606                 return_if_nok (error);
2607
2608                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2609                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2610         }
2611 }
2612
2613 static void
2614 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2615 {
2616         MONO_REQ_GC_UNSAFE_MODE;
2617
2618         GenericParamTableEntry *entry;
2619
2620         /*
2621          * The GenericParam table must be sorted according to the `owner' field.
2622          * We need to do this sorting prior to writing the GenericParamConstraint
2623          * table, since we have to use the final GenericParam table indices there
2624          * and they must also be sorted.
2625          */
2626
2627         entry = g_new0 (GenericParamTableEntry, 1);
2628         entry->owner = owner;
2629         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2630         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2631         entry->gparam = gparam;
2632         
2633         g_ptr_array_add (assembly->gen_params, entry);
2634 }
2635
2636 static gboolean
2637 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2638 {
2639         MONO_REQ_GC_UNSAFE_MODE;
2640
2641         MonoDynamicTable *table;
2642         MonoGenericParam *param;
2643         guint32 *values;
2644         guint32 table_idx;
2645
2646         mono_error_init (error);
2647
2648         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2649         table_idx = table->next_idx ++;
2650         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2651
2652         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2653         return_val_if_nok (error, FALSE);
2654
2655         param = gparam_type->data.generic_param;
2656
2657         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2658         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2659         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2660         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2661
2662         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2663                 return FALSE;
2664
2665         encode_constraints (entry->gparam, table_idx, assembly, error);
2666         return_val_if_nok (error, FALSE);
2667
2668         return TRUE;
2669 }
2670
2671 static guint32
2672 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2673 {
2674         MONO_REQ_GC_UNSAFE_MODE;
2675
2676         MonoDynamicTable *table;
2677         guint32 token;
2678         guint32 *values;
2679         guint32 cols [MONO_ASSEMBLY_SIZE];
2680         const char *pubkey;
2681         guint32 publen;
2682
2683         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2684                 return token;
2685
2686         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2687                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2688                 token = table->next_idx ++;
2689                 table->rows ++;
2690                 alloc_table (table, table->rows);
2691                 values = table->values + token * MONO_MODULEREF_SIZE;
2692                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2693
2694                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2695                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2696                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2697
2698                 return token;
2699         }
2700         
2701         if (assembly_is_dynamic (image->assembly))
2702                 /* FIXME: */
2703                 memset (cols, 0, sizeof (cols));
2704         else {
2705                 /* image->assembly->image is the manifest module */
2706                 image = image->assembly->image;
2707                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2708         }
2709
2710         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2711         token = table->next_idx ++;
2712         table->rows ++;
2713         alloc_table (table, table->rows);
2714         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2715         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2716         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2717         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2718         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2719         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2720         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2721         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2722         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2723
2724         if (strcmp ("", image->assembly->aname.culture)) {
2725                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2726                                 image->assembly->aname.culture);
2727         }
2728
2729         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2730                 guchar pubtoken [9];
2731                 pubtoken [0] = 8;
2732                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2733                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2734         } else {
2735                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2736         }
2737         token <<= MONO_RESOLUTION_SCOPE_BITS;
2738         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2739         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2740         return token;
2741 }
2742
2743 static guint32
2744 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2745 {
2746         MONO_REQ_GC_NEUTRAL_MODE;
2747
2748         MonoDynamicTable *table;
2749         guint32 *values;
2750         guint32 token;
2751         SigBuffer buf;
2752
2753         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2754                 return token;
2755
2756         sigbuffer_init (&buf, 32);
2757         switch (type->type) {
2758         case MONO_TYPE_FNPTR:
2759         case MONO_TYPE_PTR:
2760         case MONO_TYPE_SZARRAY:
2761         case MONO_TYPE_ARRAY:
2762         case MONO_TYPE_VAR:
2763         case MONO_TYPE_MVAR:
2764         case MONO_TYPE_GENERICINST:
2765                 encode_type (assembly, type, &buf);
2766                 break;
2767         case MONO_TYPE_CLASS:
2768         case MONO_TYPE_VALUETYPE: {
2769                 MonoClass *k = mono_class_from_mono_type (type);
2770                 if (!k || !k->generic_container) {
2771                         sigbuffer_free (&buf);
2772                         return 0;
2773                 }
2774                 encode_type (assembly, type, &buf);
2775                 break;
2776         }
2777         default:
2778                 sigbuffer_free (&buf);
2779                 return 0;
2780         }
2781
2782         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2783         if (assembly->save) {
2784                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2785                 alloc_table (table, table->rows + 1);
2786                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2787                 values [MONO_TYPESPEC_SIGNATURE] = token;
2788         }
2789         sigbuffer_free (&buf);
2790
2791         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2792         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2793         table->next_idx ++;
2794         return token;
2795 }
2796
2797 static guint32
2798 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2799 {
2800         MONO_REQ_GC_UNSAFE_MODE;
2801
2802         MonoDynamicTable *table;
2803         guint32 *values;
2804         guint32 token, scope, enclosing;
2805         MonoClass *klass;
2806
2807         /* if the type requires a typespec, we must try that first*/
2808         if (try_typespec && (token = create_typespec (assembly, type)))
2809                 return token;
2810         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2811         if (token)
2812                 return token;
2813         klass = mono_class_from_mono_type (type);
2814         if (!klass)
2815                 klass = mono_class_from_mono_type (type);
2816
2817         /*
2818          * If it's in the same module and not a generic type parameter:
2819          */
2820         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2821                         (type->type != MONO_TYPE_MVAR)) {
2822                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2823                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2824                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2825                 return token;
2826         }
2827
2828         if (klass->nested_in) {
2829                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2830                 /* get the typeref idx of the enclosing type */
2831                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2832                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2833         } else {
2834                 scope = resolution_scope_from_image (assembly, klass->image);
2835         }
2836         table = &assembly->tables [MONO_TABLE_TYPEREF];
2837         if (assembly->save) {
2838                 alloc_table (table, table->rows + 1);
2839                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2840                 values [MONO_TYPEREF_SCOPE] = scope;
2841                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2842                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2843         }
2844         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2845         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2846         table->next_idx ++;
2847         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2848         return token;
2849 }
2850
2851 /*
2852  * Despite the name, we handle also TypeSpec (with the above helper).
2853  */
2854 static guint32
2855 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2856 {
2857         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2858 }
2859
2860 #ifndef DISABLE_REFLECTION_EMIT
2861 static guint32
2862 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2863 {
2864         MONO_REQ_GC_NEUTRAL_MODE;
2865
2866         MonoDynamicTable *table;
2867         guint32 *values;
2868         guint32 token, pclass;
2869
2870         switch (parent & MONO_TYPEDEFORREF_MASK) {
2871         case MONO_TYPEDEFORREF_TYPEREF:
2872                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2873                 break;
2874         case MONO_TYPEDEFORREF_TYPESPEC:
2875                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2876                 break;
2877         case MONO_TYPEDEFORREF_TYPEDEF:
2878                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2879                 break;
2880         default:
2881                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2882                 return 0;
2883         }
2884         /* extract the index */
2885         parent >>= MONO_TYPEDEFORREF_BITS;
2886
2887         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2888
2889         if (assembly->save) {
2890                 alloc_table (table, table->rows + 1);
2891                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2892                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2893                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2894                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2895         }
2896
2897         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2898         table->next_idx ++;
2899
2900         return token;
2901 }
2902
2903 /*
2904  * Insert a memberef row into the metadata: the token that point to the memberref
2905  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2906  * mono_image_get_fieldref_token()).
2907  * The sig param is an index to an already built signature.
2908  */
2909 static guint32
2910 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2911 {
2912         MONO_REQ_GC_NEUTRAL_MODE;
2913
2914         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2915         return mono_image_add_memberef_row (assembly, parent, name, sig);
2916 }
2917
2918
2919 static guint32
2920 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2921 {
2922         MONO_REQ_GC_NEUTRAL_MODE;
2923
2924         guint32 token;
2925         MonoMethodSignature *sig;
2926         
2927         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2928
2929         if (create_typespec) {
2930                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2931                 if (token)
2932                         return token;
2933         } 
2934
2935         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2936         if (token && !create_typespec)
2937                 return token;
2938
2939         g_assert (!method->is_inflated);
2940         if (!token) {
2941                 /*
2942                  * A methodref signature can't contain an unmanaged calling convention.
2943                  */
2944                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2945                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2946                         sig->call_convention = MONO_CALL_DEFAULT;
2947                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2948                         method->name,  method_encode_signature (assembly, sig));
2949                 g_free (sig);
2950                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2951         }
2952
2953         if (create_typespec) {
2954                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2955                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2956                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2957
2958                 if (assembly->save) {
2959                         guint32 *values;
2960
2961                         alloc_table (table, table->rows + 1);
2962                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2963                         values [MONO_METHODSPEC_METHOD] = token;
2964                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2965                 }
2966
2967                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2968                 table->next_idx ++;
2969                 /*methodspec and memberef tokens are diferent, */
2970                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2971                 return token;
2972         }
2973         return token;
2974 }
2975
2976 static guint32
2977 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2978 {
2979         guint32 token, parent, sig;
2980         ReflectionMethodBuilder rmb;
2981         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2982         
2983         mono_error_init (error);
2984         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2985         if (token)
2986                 return token;
2987
2988         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2989                 return 0;
2990
2991         /*
2992          * A methodref signature can't contain an unmanaged calling convention.
2993          * Since some flags are encoded as part of call_conv, we need to check against it.
2994         */
2995         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2996                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2997
2998         sig = method_builder_encode_signature (assembly, &rmb, error);
2999         return_val_if_nok (error, 0);
3000
3001         if (tb->generic_params) {
3002                 parent = create_generic_typespec (assembly, tb, error);
3003                 return_val_if_nok (error, 0);
3004         } else {
3005                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
3006                 return_val_if_nok (error, 0);
3007
3008                 parent = mono_image_typedef_or_ref (assembly, t);
3009         }
3010
3011         char *name = mono_string_to_utf8_checked (method->name, error);
3012         return_val_if_nok (error, 0);
3013
3014         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3015         g_free (name);
3016
3017         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3018
3019         return token;
3020 }
3021
3022 static guint32
3023 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
3024                                      const gchar *name, guint32 sig)
3025 {
3026         MonoDynamicTable *table;
3027         guint32 token;
3028         guint32 *values;
3029         
3030         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3031
3032         if (assembly->save) {
3033                 alloc_table (table, table->rows + 1);
3034                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3035                 values [MONO_MEMBERREF_CLASS] = original;
3036                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3037                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3038         }
3039
3040         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3041         table->next_idx ++;
3042
3043         return token;
3044 }
3045
3046 static guint32
3047 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3048 {
3049         SigBuffer buf;
3050         int i;
3051         guint32 nparams = mono_array_length (mb->generic_params);
3052         guint32 idx;
3053
3054         if (!assembly->save)
3055                 return 0;
3056
3057         sigbuffer_init (&buf, 32);
3058
3059         sigbuffer_add_value (&buf, 0xa);
3060         sigbuffer_add_value (&buf, nparams);
3061
3062         for (i = 0; i < nparams; i++) {
3063                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3064                 sigbuffer_add_value (&buf, i);
3065         }
3066
3067         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3068         sigbuffer_free (&buf);
3069         return idx;
3070 }
3071
3072 static guint32
3073 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3074 {
3075         MonoDynamicTable *table;
3076         guint32 *values;
3077         guint32 token, mtoken = 0;
3078
3079         mono_error_init (error);
3080         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3081         if (token)
3082                 return token;
3083
3084         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3085
3086         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3087         if (!mono_error_ok (error))
3088                 return 0;
3089
3090         switch (mono_metadata_token_table (mtoken)) {
3091         case MONO_TABLE_MEMBERREF:
3092                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3093                 break;
3094         case MONO_TABLE_METHOD:
3095                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3096                 break;
3097         default:
3098                 g_assert_not_reached ();
3099         }
3100
3101         if (assembly->save) {
3102                 alloc_table (table, table->rows + 1);
3103                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3104                 values [MONO_METHODSPEC_METHOD] = mtoken;
3105                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3106         }
3107
3108         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3109         table->next_idx ++;
3110
3111         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3112         return token;
3113 }
3114
3115 static guint32
3116 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3117 {
3118         guint32 token;
3119
3120         mono_error_init (error);
3121
3122         if (mb->generic_params && create_methodspec) 
3123                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3124
3125         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3126         if (token)
3127                 return token;
3128
3129         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3130         if (!mono_error_ok (error))
3131                 return 0;
3132         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3133         return token;
3134 }
3135
3136 static guint32
3137 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3138 {
3139         guint32 token, parent, sig;
3140         ReflectionMethodBuilder rmb;
3141         char *name;
3142         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3143         
3144         mono_error_init (error);
3145         
3146         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3147         if (token)
3148                 return token;
3149
3150         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3151                 return 0;
3152
3153         if (tb->generic_params) {
3154                 parent = create_generic_typespec (assembly, tb, error);
3155                 return_val_if_nok (error, 0);
3156         } else {
3157                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3158                 return_val_if_nok (error, 0);
3159                 parent = mono_image_typedef_or_ref (assembly, type);
3160         }
3161         
3162         name = mono_string_to_utf8_checked (rmb.name, error);
3163         return_val_if_nok (error, 0);
3164         sig = method_builder_encode_signature (assembly, &rmb, error);
3165         return_val_if_nok (error, 0);
3166
3167         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3168
3169         g_free (name);
3170         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3171         return token;
3172 }
3173 #endif
3174
3175 static gboolean
3176 is_field_on_inst (MonoClassField *field)
3177 {
3178         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3179 }
3180
3181 /*
3182  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3183  */
3184 static MonoType*
3185 get_field_on_inst_generic_type (MonoClassField *field)
3186 {
3187         MonoClass *klass, *gtd;
3188         MonoDynamicGenericClass *dgclass;
3189         int field_index;
3190
3191         g_assert (is_field_on_inst (field));
3192
3193         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3194
3195         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3196                 field_index = field - dgclass->fields;
3197                 return dgclass->field_generic_types [field_index];              
3198         }
3199
3200         klass = field->parent;
3201         gtd = klass->generic_class->container_class;
3202
3203         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3204                 field_index = field - klass->fields;
3205                 return gtd->fields [field_index].type;
3206         }
3207
3208         g_assert_not_reached ();
3209         return 0;
3210 }
3211
3212 #ifndef DISABLE_REFLECTION_EMIT
3213 static guint32
3214 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3215 {
3216         MonoType *type;
3217         guint32 token;
3218
3219         g_assert (field);
3220         g_assert (field->parent);
3221
3222         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3223         if (token)
3224                 return token;
3225
3226         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3227                 int index = field - field->parent->fields;
3228                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3229         } else {
3230                 if (is_field_on_inst (field))
3231                         type = get_field_on_inst_generic_type (field);
3232                 else
3233                         type = mono_field_get_type (field);
3234         }
3235         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3236                                                                                         mono_field_get_name (field),
3237                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3238         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3239         return token;
3240 }
3241
3242 static guint32
3243 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3244 {
3245         guint32 token;
3246         MonoClass *klass;
3247         MonoGenericClass *gclass;
3248         MonoType *type;
3249         char *name;
3250
3251         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3252         if (token)
3253                 return token;
3254         if (is_sre_field_builder (mono_object_class (f->fb))) {
3255                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3256                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3257                 return_val_if_nok (error, 0);
3258                 klass = mono_class_from_mono_type (type);
3259                 gclass = type->data.generic_class;
3260                 g_assert (gclass->is_dynamic);
3261
3262                 guint32 sig_token = field_encode_signature (assembly, fb, error);
3263                 return_val_if_nok (error, 0);
3264                 name = mono_string_to_utf8_checked (fb->name, error);
3265                 return_val_if_nok (error, 0);
3266                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3267                 g_free (name);          
3268         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3269                 guint32 sig;
3270                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3271
3272                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3273                 return_val_if_nok (error, 0);
3274                 klass = mono_class_from_mono_type (type);
3275
3276                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3277                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3278         } else {
3279                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3280                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3281         }
3282
3283         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3284         return token;
3285 }
3286
3287 static guint32
3288 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3289 {
3290         guint32 sig, token;
3291         MonoClass *klass;
3292         MonoGenericClass *gclass;
3293         MonoType *type;
3294
3295         mono_error_init (error);
3296
3297         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3298
3299         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3300         if (token)
3301                 return token;
3302
3303         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3304                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3305                 ReflectionMethodBuilder rmb;
3306                 char *name;
3307
3308                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3309                 return_val_if_nok (error, 0);
3310                 klass = mono_class_from_mono_type (type);
3311
3312                 gclass = type->data.generic_class;
3313                 g_assert (gclass->is_dynamic);
3314
3315                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3316                         return 0;
3317
3318                 sig = method_builder_encode_signature (assembly, &rmb, error);
3319                 return_val_if_nok (error, 0);
3320
3321                 name = mono_string_to_utf8_checked (rmb.name, error);
3322                 return_val_if_nok (error, 0);
3323
3324                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3325                 g_free (name);
3326         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3327                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3328
3329                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3330                 return_val_if_nok (error, 0);
3331                 klass = mono_class_from_mono_type (type);
3332
3333                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3334                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3335         } else {
3336                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3337                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3338         }
3339
3340
3341         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3342         return token;
3343 }
3344
3345 static MonoMethod*
3346 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3347 {
3348         MonoClass *klass;
3349         MonoGenericContext tmp_context;
3350         MonoType **type_argv;
3351         MonoGenericInst *ginst;
3352         MonoMethod *method, *inflated;
3353         int count, i;
3354
3355         mono_error_init (error);
3356
3357         init_type_builder_generics ((MonoObject*)m->inst, error);
3358         return_val_if_nok (error, NULL);
3359
3360         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3361         return_val_if_nok (error, NULL);
3362
3363         klass = method->klass;
3364
3365         if (m->method_args == NULL)
3366                 return method;
3367
3368         if (method->is_inflated)
3369                 method = ((MonoMethodInflated *) method)->declaring;
3370
3371         count = mono_array_length (m->method_args);
3372
3373         type_argv = g_new0 (MonoType *, count);
3374         for (i = 0; i < count; i++) {
3375                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3376                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3377                 return_val_if_nok (error, NULL);
3378         }
3379         ginst = mono_metadata_get_generic_inst (count, type_argv);
3380         g_free (type_argv);
3381
3382         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3383         tmp_context.method_inst = ginst;
3384
3385         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3386         mono_error_assert_ok (error);
3387         return inflated;
3388 }
3389
3390 static guint32
3391 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3392 {
3393         guint32 sig, token = 0;
3394         MonoType *type;
3395         MonoClass *klass;
3396
3397         mono_error_init (error);
3398
3399         if (m->method_args) {
3400                 MonoMethod *inflated;
3401
3402                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3403                 return_val_if_nok (error, 0);
3404
3405                 if (create_methodspec)
3406                         token = mono_image_get_methodspec_token (assembly, inflated);
3407                 else
3408                         token = mono_image_get_inflated_method_token (assembly, inflated);
3409                 return token;
3410         }
3411
3412         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3413         if (token)
3414                 return token;
3415
3416         if (is_sre_method_builder (mono_object_class (m->mb))) {
3417                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3418                 MonoGenericClass *gclass;
3419                 ReflectionMethodBuilder rmb;
3420                 char *name;
3421
3422                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3423                 return_val_if_nok (error, 0);
3424                 klass = mono_class_from_mono_type (type);
3425                 gclass = type->data.generic_class;
3426                 g_assert (gclass->is_dynamic);
3427
3428                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3429                         return 0;
3430
3431                 sig = method_builder_encode_signature (assembly, &rmb, error);
3432                 return_val_if_nok (error, 0);
3433
3434                 name = mono_string_to_utf8_checked (rmb.name, error);
3435                 return_val_if_nok (error, 0);
3436
3437                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3438                 g_free (name);          
3439         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3440                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3441
3442                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3443                 return_val_if_nok (error, 0);
3444                 klass = mono_class_from_mono_type (type);
3445
3446                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3447                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3448         } else {
3449                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3450                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3451         }
3452
3453         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3454         return token;
3455 }
3456
3457 static guint32
3458 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3459 {
3460         SigBuffer buf;
3461         int i;
3462         guint32 nparams = context->method_inst->type_argc;
3463         guint32 idx;
3464
3465         if (!assembly->save)
3466                 return 0;
3467
3468         sigbuffer_init (&buf, 32);
3469         /*
3470          * FIXME: vararg, explicit_this, differenc call_conv values...
3471          */
3472         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3473         sigbuffer_add_value (&buf, nparams);
3474
3475         for (i = 0; i < nparams; i++)
3476                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3477
3478         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3479         sigbuffer_free (&buf);
3480         return idx;
3481 }
3482
3483 static guint32
3484 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3485 {
3486         MonoDynamicTable *table;
3487         guint32 *values;
3488         guint32 token, mtoken = 0, sig;
3489         MonoMethodInflated *imethod;
3490         MonoMethod *declaring;
3491
3492         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3493
3494         g_assert (method->is_inflated);
3495         imethod = (MonoMethodInflated *) method;
3496         declaring = imethod->declaring;
3497
3498         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3499         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3500
3501         if (!mono_method_signature (declaring)->generic_param_count)
3502                 return mtoken;
3503
3504         switch (mono_metadata_token_table (mtoken)) {
3505         case MONO_TABLE_MEMBERREF:
3506                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3507                 break;
3508         case MONO_TABLE_METHOD:
3509                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3510                 break;
3511         default:
3512                 g_assert_not_reached ();
3513         }
3514
3515         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3516
3517         if (assembly->save) {
3518                 alloc_table (table, table->rows + 1);
3519                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3520                 values [MONO_METHODSPEC_METHOD] = mtoken;
3521                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3522         }
3523
3524         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3525         table->next_idx ++;
3526
3527         return token;
3528 }
3529
3530 static guint32
3531 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3532 {
3533         MonoMethodInflated *imethod;
3534         guint32 token;
3535         
3536         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3537         if (token)
3538                 return token;
3539
3540         g_assert (method->is_inflated);
3541         imethod = (MonoMethodInflated *) method;
3542
3543         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3544                 token = method_encode_methodspec (assembly, method);
3545         } else {
3546                 guint32 sig = method_encode_signature (
3547                         assembly, mono_method_signature (imethod->declaring));
3548                 token = mono_image_get_memberref_token (
3549                         assembly, &method->klass->byval_arg, method->name, sig);
3550         }
3551
3552         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3553         return token;
3554 }
3555
3556 static guint32
3557 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3558 {
3559         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3560         guint32 sig, token;
3561
3562         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3563         token = mono_image_get_memberref_token (
3564                 assembly, &m->klass->byval_arg, m->name, sig);
3565
3566         return token;
3567 }
3568
3569 static guint32
3570 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3571 {
3572         MonoDynamicTable *table;
3573         MonoClass *klass;
3574         MonoType *type;
3575         guint32 *values;
3576         guint32 token;
3577         SigBuffer buf;
3578         int count, i;
3579
3580         /*
3581          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3582          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3583          * Because of this, we must not insert it into the `typeref' hash table.
3584          */
3585         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3586         return_val_if_nok (error, 0);
3587         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3588         if (token)
3589                 return token;
3590
3591         sigbuffer_init (&buf, 32);
3592
3593         g_assert (tb->generic_params);
3594         klass = mono_class_from_mono_type (type);
3595
3596         if (tb->generic_container) {
3597                 if (!mono_reflection_create_generic_class (tb, error))
3598                         goto fail;
3599         }
3600
3601         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3602         g_assert (klass->generic_container);
3603         sigbuffer_add_value (&buf, klass->byval_arg.type);
3604         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3605
3606         count = mono_array_length (tb->generic_params);
3607         sigbuffer_add_value (&buf, count);
3608         for (i = 0; i < count; i++) {
3609                 MonoReflectionGenericParam *gparam;
3610
3611                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3612                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3613                 if (!is_ok (error))
3614                         goto fail;
3615
3616                 encode_type (assembly, gparam_type, &buf);
3617         }
3618
3619         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3620
3621         if (assembly->save) {
3622                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3623                 alloc_table (table, table->rows + 1);
3624                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3625                 values [MONO_TYPESPEC_SIGNATURE] = token;
3626         }
3627         sigbuffer_free (&buf);
3628
3629         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3630         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3631         table->next_idx ++;
3632         return token;
3633 fail:
3634         sigbuffer_free (&buf);
3635         return 0;
3636 }
3637
3638 /*
3639  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3640  */
3641 static MonoType*
3642 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3643 {
3644         int i, count, len, pos;
3645         MonoType *t;
3646
3647         mono_error_init (error);
3648
3649         count = 0;
3650         if (modreq)
3651                 count += mono_array_length (modreq);
3652         if (modopt)
3653                 count += mono_array_length (modopt);
3654
3655         if (count == 0)
3656                 return mono_metadata_type_dup (NULL, type);
3657
3658         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3659         t = (MonoType *)g_malloc (len);
3660         memcpy (t, type, MONO_SIZEOF_TYPE);
3661
3662         t->num_mods = count;
3663         pos = 0;
3664         if (modreq) {
3665                 for (i = 0; i < mono_array_length (modreq); ++i) {
3666                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3667                         if (!is_ok (error))
3668                                 goto fail;
3669                         t->modifiers [pos].required = 1;
3670                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3671                         pos ++;
3672                 }
3673         }
3674         if (modopt) {
3675                 for (i = 0; i < mono_array_length (modopt); ++i) {
3676                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3677                         if (!is_ok (error))
3678                                 goto fail;
3679                         t->modifiers [pos].required = 0;
3680                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3681                         pos ++;
3682                 }
3683         }
3684
3685         return t;
3686 fail:
3687         g_free (t);
3688         return NULL;
3689 }
3690
3691 static void
3692 init_type_builder_generics (MonoObject *type, MonoError *error)
3693 {
3694         MonoReflectionTypeBuilder *tb;
3695
3696         mono_error_init (error);
3697
3698         if (!is_sre_type_builder(mono_object_class (type)))
3699                 return;
3700         tb = (MonoReflectionTypeBuilder *)type;
3701
3702         if (tb && tb->generic_container)
3703                 mono_reflection_create_generic_class (tb, error);
3704 }
3705
3706 static guint32
3707 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3708 {
3709         MonoDynamicTable *table;
3710         MonoType *custom = NULL, *type;
3711         guint32 *values;
3712         guint32 token, pclass, parent, sig;
3713         gchar *name;
3714
3715         mono_error_init (error);
3716
3717         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3718         if (token)
3719                 return token;
3720
3721         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3722         return_val_if_nok (error, 0);
3723         /* FIXME: is this call necessary? */
3724         mono_class_from_mono_type (typeb);
3725
3726         /*FIXME this is one more layer of ugliness due how types are created.*/
3727         init_type_builder_generics (fb->type, error);
3728         return_val_if_nok (error, 0);
3729
3730         /* fb->type does not include the custom modifiers */
3731         /* FIXME: We should do this in one place when a fieldbuilder is created */
3732         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3733         return_val_if_nok (error, 0);
3734
3735         if (fb->modreq || fb->modopt) {
3736                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3737                 return_val_if_nok (error, 0);
3738         }
3739
3740         sig = fieldref_encode_signature (assembly, NULL, type);
3741         g_free (custom);
3742
3743         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3744         return_val_if_nok (error, 0);
3745         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3746         
3747         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3748         parent >>= MONO_TYPEDEFORREF_BITS;
3749
3750         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3751
3752         name = mono_string_to_utf8_checked (fb->name, error);
3753         return_val_if_nok (error, 0);
3754
3755         if (assembly->save) {
3756                 alloc_table (table, table->rows + 1);
3757                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3758                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3759                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3760                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3761         }
3762
3763         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3764         table->next_idx ++;
3765         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3766         g_free (name);
3767         return token;
3768 }
3769
3770 static guint32
3771 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3772 {
3773         SigBuffer buf;
3774         guint32 nargs;
3775         guint32 i, idx;
3776
3777         mono_error_init (error);
3778
3779         if (!assembly->save)
3780                 return 0;
3781
3782         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3783         g_assert (helper->type == 2);
3784
3785         if (helper->arguments)
3786                 nargs = mono_array_length (helper->arguments);
3787         else
3788                 nargs = 0;
3789
3790         sigbuffer_init (&buf, 32);
3791
3792         /* Encode calling convention */
3793         /* Change Any to Standard */
3794         if ((helper->call_conv & 0x03) == 0x03)
3795                 helper->call_conv = 0x01;
3796         /* explicit_this implies has_this */
3797         if (helper->call_conv & 0x40)
3798                 helper->call_conv &= 0x20;
3799
3800         if (helper->call_conv == 0) { /* Unmanaged */
3801                 idx = helper->unmanaged_call_conv - 1;
3802         } else {
3803                 /* Managed */
3804                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3805                 if (helper->call_conv & 0x02) /* varargs */
3806                         idx += 0x05;
3807         }
3808
3809         sigbuffer_add_byte (&buf, idx);
3810         sigbuffer_add_value (&buf, nargs);
3811         encode_reflection_type (assembly, helper->return_type, &buf, error);
3812         if (!is_ok (error))
3813                 goto fail;
3814         for (i = 0; i < nargs; ++i) {
3815                 MonoArray *modreqs = NULL;
3816                 MonoArray *modopts = NULL;
3817                 MonoReflectionType *pt;
3818
3819                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3820                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3821                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3822                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3823
3824                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3825                 if (!is_ok (error))
3826                         goto fail;
3827                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3828                 encode_reflection_type (assembly, pt, &buf, error);
3829                 if (!is_ok (error))
3830                         goto fail;
3831         }
3832         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3833         sigbuffer_free (&buf);
3834
3835         return idx;
3836 fail:
3837         sigbuffer_free (&buf);
3838         return 0;
3839 }
3840
3841 static guint32 
3842 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3843 {
3844         guint32 idx;
3845         MonoDynamicTable *table;
3846         guint32 *values;
3847
3848         mono_error_init (error);
3849
3850         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3851         idx = table->next_idx ++;
3852         table->rows ++;
3853         alloc_table (table, table->rows);
3854         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3855
3856         values [MONO_STAND_ALONE_SIGNATURE] =
3857                 mono_reflection_encode_sighelper (assembly, helper, error);
3858         return_val_if_nok (error, 0);
3859         
3860         return idx;
3861 }
3862
3863 static int
3864 reflection_cc_to_file (int call_conv) {
3865         switch (call_conv & 0x3) {
3866         case 0:
3867         case 1: return MONO_CALL_DEFAULT;
3868         case 2: return MONO_CALL_VARARG;
3869         default:
3870                 g_assert_not_reached ();
3871         }
3872         return 0;
3873 }
3874 #endif /* !DISABLE_REFLECTION_EMIT */
3875
3876 typedef struct {
3877         MonoType *parent;
3878         MonoMethodSignature *sig;
3879         char *name;
3880         guint32 token;
3881 } ArrayMethod;
3882
3883 #ifndef DISABLE_REFLECTION_EMIT
3884 static guint32
3885 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3886 {
3887         guint32 nparams, i;
3888         GList *tmp;
3889         char *name = NULL;
3890         MonoMethodSignature *sig;
3891         ArrayMethod *am = NULL;
3892         MonoType *mtype;
3893
3894         mono_error_init (error);
3895
3896         nparams = mono_array_length (m->parameters);
3897         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3898         sig->hasthis = 1;
3899         sig->sentinelpos = -1;
3900         sig->call_convention = reflection_cc_to_file (m->call_conv);
3901         sig->param_count = nparams;
3902         if (m->ret) {
3903                 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3904                 if (!is_ok (error))
3905                         goto fail;
3906         } else
3907                 sig->ret = &mono_defaults.void_class->byval_arg;
3908
3909         mtype = mono_reflection_type_get_handle (m->parent, error);
3910         if (!is_ok (error))
3911                 goto fail;
3912
3913         for (i = 0; i < nparams; ++i) {
3914                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3915                 if (!is_ok (error))
3916                         goto fail;
3917         }
3918
3919         name = mono_string_to_utf8_checked (m->name, error);
3920         if (!is_ok (error))
3921                 goto fail;
3922         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3923                 am = (ArrayMethod *)tmp->data;
3924                 if (strcmp (name, am->name) == 0 && 
3925                                 mono_metadata_type_equal (am->parent, mtype) &&
3926                                 mono_metadata_signature_equal (am->sig, sig)) {
3927                         g_free (name);
3928                         g_free (sig);
3929                         m->table_idx = am->token & 0xffffff;
3930                         return am->token;
3931                 }
3932         }
3933         am = g_new0 (ArrayMethod, 1);
3934         am->name = name;
3935         am->sig = sig;
3936         am->parent = mtype;
3937         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3938                 method_encode_signature (assembly, sig));
3939         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3940         m->table_idx = am->token & 0xffffff;
3941         return am->token;
3942 fail:
3943         g_free (am);
3944         g_free (name);
3945         g_free (sig);
3946         return 0;
3947
3948 }
3949
3950 /*
3951  * Insert into the metadata tables all the info about the TypeBuilder tb.
3952  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3953  */
3954 static gboolean
3955 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3956 {
3957         MonoDynamicTable *table;
3958         guint *values;
3959         int i, is_object = 0, is_system = 0;
3960         char *n;
3961
3962         mono_error_init (error);
3963
3964         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3965         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3966         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3967         n = mono_string_to_utf8_checked (tb->name, error);
3968         return_val_if_nok (error, FALSE);
3969         if (strcmp (n, "Object") == 0)
3970                 is_object++;
3971         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3972         g_free (n);
3973         n = mono_string_to_utf8_checked (tb->nspace, error);
3974         return_val_if_nok (error, FALSE);
3975         if (strcmp (n, "System") == 0)
3976                 is_system++;
3977         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3978         g_free (n);
3979         if (tb->parent && !(is_system && is_object) && 
3980                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3981                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3982                 return_val_if_nok (error, FALSE);
3983                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3984         } else {
3985                 values [MONO_TYPEDEF_EXTENDS] = 0;
3986         }
3987         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3988         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3989
3990         /*
3991          * if we have explicitlayout or sequentiallayouts, output data in the
3992          * ClassLayout table.
3993          */
3994         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3995                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3996                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3997                 table->rows++;
3998                 alloc_table (table, table->rows);
3999                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
4000                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
4001                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
4002                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
4003         }
4004
4005         /* handle interfaces */
4006         if (tb->interfaces) {
4007                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4008                 i = table->rows;
4009                 table->rows += mono_array_length (tb->interfaces);
4010                 alloc_table (table, table->rows);
4011                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
4012                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
4013                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
4014                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
4015                         return_val_if_nok (error, FALSE);
4016                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
4017                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
4018                         values += MONO_INTERFACEIMPL_SIZE;
4019                 }
4020         }
4021
4022         /* handle fields */
4023         if (tb->fields) {
4024                 table = &assembly->tables [MONO_TABLE_FIELD];
4025                 table->rows += tb->num_fields;
4026                 alloc_table (table, table->rows);
4027                 for (i = 0; i < tb->num_fields; ++i) {
4028                         mono_image_get_field_info (
4029                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
4030                         return_val_if_nok (error, FALSE);
4031                 }
4032         }
4033
4034         /* handle constructors */
4035         if (tb->ctors) {
4036                 table = &assembly->tables [MONO_TABLE_METHOD];
4037                 table->rows += mono_array_length (tb->ctors);
4038                 alloc_table (table, table->rows);
4039                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4040                         if (!mono_image_get_ctor_info (domain,
4041                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
4042                                                        assembly, error))
4043                                 return FALSE;
4044                 }
4045         }
4046
4047         /* handle methods */
4048         if (tb->methods) {
4049                 table = &assembly->tables [MONO_TABLE_METHOD];
4050                 table->rows += tb->num_methods;
4051                 alloc_table (table, table->rows);
4052                 for (i = 0; i < tb->num_methods; ++i) {
4053                         if (!mono_image_get_method_info (
4054                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4055                                 return FALSE;
4056                 }
4057         }
4058
4059         /* Do the same with properties etc.. */
4060         if (tb->events && mono_array_length (tb->events)) {
4061                 table = &assembly->tables [MONO_TABLE_EVENT];
4062                 table->rows += mono_array_length (tb->events);
4063                 alloc_table (table, table->rows);
4064                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4065                 table->rows ++;
4066                 alloc_table (table, table->rows);
4067                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4068                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4069                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4070                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4071                         mono_image_get_event_info (
4072                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4073                         return_val_if_nok (error, FALSE);
4074                 }
4075         }
4076         if (tb->properties && mono_array_length (tb->properties)) {
4077                 table = &assembly->tables [MONO_TABLE_PROPERTY];
4078                 table->rows += mono_array_length (tb->properties);
4079                 alloc_table (table, table->rows);
4080                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4081                 table->rows ++;
4082                 alloc_table (table, table->rows);
4083                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4084                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4085                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4086                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4087                         mono_image_get_property_info (
4088                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4089                         return_val_if_nok (error, FALSE);
4090                 }
4091         }
4092
4093         /* handle generic parameters */
4094         if (tb->generic_params) {
4095                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4096                 table->rows += mono_array_length (tb->generic_params);
4097                 alloc_table (table, table->rows);
4098                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4099                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4100
4101                         mono_image_get_generic_param_info (
4102                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4103                 }
4104         }
4105
4106         mono_image_add_decl_security (assembly, 
4107                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4108
4109         if (tb->subtypes) {
4110                 MonoDynamicTable *ntable;
4111                 
4112                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4113                 ntable->rows += mono_array_length (tb->subtypes);
4114                 alloc_table (ntable, ntable->rows);
4115                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4116
4117                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4118                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4119
4120                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4121                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4122                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4123                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4124                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4125                                 ntable->next_idx, ntable->rows);*/
4126                         values += MONO_NESTED_CLASS_SIZE;
4127                         ntable->next_idx++;
4128                 }
4129         }
4130
4131         return TRUE;
4132 }
4133 #endif
4134
4135 static void
4136 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4137 {
4138         int i;
4139
4140         mono_ptr_array_append (*types, type);
4141
4142         if (!type->subtypes)
4143                 return;
4144
4145         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4146                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4147                 collect_types (types, subtype);
4148         }
4149 }
4150
4151 static gint
4152 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4153 {
4154         if ((*type1)->table_idx < (*type2)->table_idx)
4155                 return -1;
4156         else
4157                 if ((*type1)->table_idx > (*type2)->table_idx)
4158                         return 1;
4159         else
4160                 return 0;
4161 }
4162
4163 static gboolean
4164 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4165         int i;
4166
4167         mono_error_init (error);
4168         if (!pinfo)
4169                 return TRUE;
4170         for (i = 0; i < mono_array_length (pinfo); ++i) {
4171                 MonoReflectionParamBuilder *pb;
4172                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4173                 if (!pb)
4174                         continue;
4175                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4176                         return FALSE;
4177         }
4178
4179         return TRUE;
4180 }
4181
4182 static gboolean
4183 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4184         int i;
4185
4186         mono_error_init (error);
4187         
4188         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4189                 return FALSE;
4190         if (tb->fields) {
4191                 for (i = 0; i < tb->num_fields; ++i) {
4192                         MonoReflectionFieldBuilder* fb;
4193                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4194                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4195                                 return FALSE;
4196                 }
4197         }
4198         if (tb->events) {
4199                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4200                         MonoReflectionEventBuilder* eb;
4201                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4202                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4203                                 return FALSE;
4204                 }
4205         }
4206         if (tb->properties) {
4207                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4208                         MonoReflectionPropertyBuilder* pb;
4209                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4210                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4211                                 return FALSE;
4212                 }
4213         }
4214         if (tb->ctors) {
4215                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4216                         MonoReflectionCtorBuilder* cb;
4217                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4218                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4219                             !params_add_cattrs (assembly, cb->pinfo, error))
4220                                 return FALSE;
4221                 }
4222         }
4223
4224         if (tb->methods) {
4225                 for (i = 0; i < tb->num_methods; ++i) {
4226                         MonoReflectionMethodBuilder* mb;
4227                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4228                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4229                             !params_add_cattrs (assembly, mb->pinfo, error))
4230                                 return FALSE;
4231                 }
4232         }
4233
4234         if (tb->subtypes) {
4235                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4236                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4237                                 return FALSE;
4238                 }
4239         }
4240
4241         return TRUE;
4242 }
4243
4244 static gboolean
4245 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4246 {
4247         int i;
4248         
4249         mono_error_init (error);
4250
4251         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4252                 return FALSE;
4253
4254         if (moduleb->global_methods) {
4255                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4256                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4257                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4258                             !params_add_cattrs (assembly, mb->pinfo, error))
4259                                 return FALSE;
4260                 }
4261         }
4262
4263         if (moduleb->global_fields) {
4264                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4265                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4266                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4267                                 return FALSE;
4268                 }
4269         }
4270         
4271         if (moduleb->types) {
4272                 for (i = 0; i < moduleb->num_types; ++i) {
4273                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4274                                 return FALSE;
4275                 }
4276         }
4277
4278         return TRUE;
4279 }
4280
4281 static gboolean
4282 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly, MonoError *error)
4283 {
4284         MonoDynamicTable *table;
4285         guint32 *values;
4286         char blob_size [6];
4287         guchar hash [20];
4288         char *b = blob_size;
4289         char *dir, *path;
4290
4291         mono_error_init (error);
4292
4293         table = &assembly->tables [MONO_TABLE_FILE];
4294         table->rows++;
4295         alloc_table (table, table->rows);
4296         values = table->values + table->next_idx * MONO_FILE_SIZE;
4297         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4298         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4299         if (image_is_dynamic (module->image)) {
4300                 /* This depends on the fact that the main module is emitted last */
4301                 dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, error);
4302                 return_val_if_nok (error, FALSE);
4303                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4304         } else {
4305                 dir = NULL;
4306                 path = g_strdup (module->image->name);
4307         }
4308         mono_sha1_get_digest_from_file (path, hash);
4309         g_free (dir);
4310         g_free (path);
4311         mono_metadata_encode_value (20, b, &b);
4312         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4313         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4314         table->next_idx ++;
4315         return TRUE;
4316 }
4317
4318 static void
4319 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
4320 {
4321         MonoDynamicTable *table;
4322         int i;
4323
4324         mono_error_init (error);
4325
4326         table = &assembly->tables [MONO_TABLE_MODULE];
4327         mb->table_idx = table->next_idx ++;
4328         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name, error);
4329         return_if_nok (error);
4330         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4331         i /= 16;
4332         ++i;
4333         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4334         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4335         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4336         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4337 }
4338
4339 static guint32
4340 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4341         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4342 {
4343         MonoDynamicTable *table;
4344         guint32 *values;
4345         guint32 visib, res;
4346
4347         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4348         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4349                 return 0;
4350
4351         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4352         table->rows++;
4353         alloc_table (table, table->rows);
4354         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4355
4356         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4357         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4358         if (klass->nested_in)
4359                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4360         else
4361                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4362         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4363         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4364
4365         res = table->next_idx;
4366
4367         table->next_idx ++;
4368
4369         /* Emit nested types */
4370         if (klass->ext && klass->ext->nested_classes) {
4371                 GList *tmp;
4372
4373                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4374                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4375         }
4376
4377         return res;
4378 }
4379
4380 static void
4381 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4382                               guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4383                               MonoError *error)
4384 {
4385         MonoClass *klass;
4386         guint32 idx, i;
4387
4388         mono_error_init (error);
4389
4390         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4391         return_if_nok (error);
4392
4393         klass = mono_class_from_mono_type (t);
4394
4395         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4396
4397         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4398                                                                                                    parent_index, assembly);
4399
4400         /* 
4401          * Emit nested types
4402          * We need to do this ourselves since klass->nested_classes is not set up.
4403          */
4404         if (tb->subtypes) {
4405                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4406                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4407                         return_if_nok (error);
4408                 }
4409         }
4410 }
4411
4412 static void
4413 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4414         guint32 module_index, MonoDynamicImage *assembly)
4415 {
4416         MonoImage *image = module->image;
4417         MonoTableInfo  *t;
4418         guint32 i;
4419
4420         t = &image->tables [MONO_TABLE_TYPEDEF];
4421
4422         for (i = 0; i < t->rows; ++i) {
4423                 MonoError error;
4424                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4425                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4426
4427                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4428                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4429         }
4430 }
4431
4432 static void
4433 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4434 {
4435         MonoDynamicTable *table;
4436         guint32 *values;
4437         guint32 scope, scope_idx, impl, current_idx;
4438         gboolean forwarder = TRUE;
4439         gpointer iter = NULL;
4440         MonoClass *nested;
4441
4442         if (klass->nested_in) {
4443                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4444                 forwarder = FALSE;
4445         } else {
4446                 scope = resolution_scope_from_image (assembly, klass->image);
4447                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4448                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4449                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4450         }
4451
4452         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4453
4454         table->rows++;
4455         alloc_table (table, table->rows);
4456         current_idx = table->next_idx;
4457         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4458
4459         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4460         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4461         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4462         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4463         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4464
4465         table->next_idx++;
4466
4467         while ((nested = mono_class_get_nested_types (klass, &iter)))
4468                 add_exported_type (assemblyb, assembly, nested, current_idx);
4469 }
4470
4471 static void
4472 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4473 {
4474         MonoError error;
4475         MonoClass *klass;
4476         int i;
4477
4478         if (!assemblyb->type_forwarders)
4479                 return;
4480
4481         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4482                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4483                 MonoType *type;
4484                 if (!t)
4485                         continue;
4486
4487                 type = mono_reflection_type_get_handle (t, &error);
4488                 mono_error_assert_ok (&error);
4489                 g_assert (type);
4490
4491                 klass = mono_class_from_mono_type (type);
4492
4493                 add_exported_type (assemblyb, assembly, klass, 0);
4494         }
4495 }
4496
4497 #define align_pointer(base,p)\
4498         do {\
4499                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4500                 if (__diff & 3)\
4501                         (p) += 4 - (__diff & 3);\
4502         } while (0)
4503
4504 static int
4505 compare_constants (const void *a, const void *b)
4506 {
4507         const guint32 *a_values = (const guint32 *)a;
4508         const guint32 *b_values = (const guint32 *)b;
4509         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4510 }
4511
4512 static int
4513 compare_semantics (const void *a, const void *b)
4514 {
4515         const guint32 *a_values = (const guint32 *)a;
4516         const guint32 *b_values = (const guint32 *)b;
4517         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4518         if (assoc)
4519                 return assoc;
4520         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4521 }
4522
4523 static int
4524 compare_custom_attrs (const void *a, const void *b)
4525 {
4526         const guint32 *a_values = (const guint32 *)a;
4527         const guint32 *b_values = (const guint32 *)b;
4528
4529         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4530 }
4531
4532 static int
4533 compare_field_marshal (const void *a, const void *b)
4534 {
4535         const guint32 *a_values = (const guint32 *)a;
4536         const guint32 *b_values = (const guint32 *)b;
4537
4538         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4539 }
4540
4541 static int
4542 compare_nested (const void *a, const void *b)
4543 {
4544         const guint32 *a_values = (const guint32 *)a;
4545         const guint32 *b_values = (const guint32 *)b;
4546
4547         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4548 }
4549
4550 static int
4551 compare_genericparam (const void *a, const void *b)
4552 {
4553         MonoError error;
4554         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4555         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4556
4557         if ((*b_entry)->owner == (*a_entry)->owner) {
4558                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4559                 mono_error_assert_ok (&error);
4560                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4561                 mono_error_assert_ok (&error);
4562                 return 
4563                         mono_type_get_generic_param_num (a_type) -
4564                         mono_type_get_generic_param_num (b_type);
4565         } else
4566                 return (*a_entry)->owner - (*b_entry)->owner;
4567 }
4568
4569 static int
4570 compare_declsecurity_attrs (const void *a, const void *b)
4571 {
4572         const guint32 *a_values = (const guint32 *)a;
4573         const guint32 *b_values = (const guint32 *)b;
4574
4575         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4576 }
4577
4578 static int
4579 compare_interface_impl (const void *a, const void *b)
4580 {
4581         const guint32 *a_values = (const guint32 *)a;
4582         const guint32 *b_values = (const guint32 *)b;
4583
4584         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4585         if (klass)
4586                 return klass;
4587
4588         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4589 }
4590
4591 static void
4592 pad_heap (MonoDynamicStream *sh)
4593 {
4594         if (sh->index & 3) {
4595                 int sz = 4 - (sh->index & 3);
4596                 memset (sh->data + sh->index, 0, sz);
4597                 sh->index += sz;
4598         }
4599 }
4600
4601 struct StreamDesc {
4602         const char *name;
4603         MonoDynamicStream *stream;
4604 };
4605
4606 /*
4607  * build_compressed_metadata() fills in the blob of data that represents the 
4608  * raw metadata as it will be saved in the PE file. The five streams are output 
4609  * and the metadata tables are comnpressed from the guint32 array representation, 
4610  * to the compressed on-disk format.
4611  */
4612 static gboolean
4613 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4614 {
4615         MonoDynamicTable *table;
4616         int i;
4617         guint64 valid_mask = 0;
4618         guint64 sorted_mask;
4619         guint32 heapt_size = 0;
4620         guint32 meta_size = 256; /* allow for header and other stuff */
4621         guint32 table_offset;
4622         guint32 ntables = 0;
4623         guint64 *int64val;
4624         guint32 *int32val;
4625         guint16 *int16val;
4626         MonoImage *meta;
4627         unsigned char *p;
4628         struct StreamDesc stream_desc [5];
4629
4630         mono_error_init (error);
4631
4632         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4633         for (i = 0; i < assembly->gen_params->len; i++) {
4634                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4635                 if (!write_generic_param_entry (assembly, entry, error))
4636                         return FALSE;
4637         }
4638
4639         stream_desc [0].name  = "#~";
4640         stream_desc [0].stream = &assembly->tstream;
4641         stream_desc [1].name  = "#Strings";
4642         stream_desc [1].stream = &assembly->sheap;
4643         stream_desc [2].name  = "#US";
4644         stream_desc [2].stream = &assembly->us;
4645         stream_desc [3].name  = "#Blob";
4646         stream_desc [3].stream = &assembly->blob;
4647         stream_desc [4].name  = "#GUID";
4648         stream_desc [4].stream = &assembly->guid;
4649         
4650         /* tables that are sorted */
4651         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4652                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4653                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4654                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4655                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4656                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4657                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4658         
4659         /* Compute table sizes */
4660         /* the MonoImage has already been created in mono_image_basic_init() */
4661         meta = &assembly->image;
4662
4663         /* sizes should be multiple of 4 */
4664         pad_heap (&assembly->blob);
4665         pad_heap (&assembly->guid);
4666         pad_heap (&assembly->sheap);
4667         pad_heap (&assembly->us);
4668
4669         /* Setup the info used by compute_sizes () */
4670         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4671         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4672         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4673
4674         meta_size += assembly->blob.index;
4675         meta_size += assembly->guid.index;
4676         meta_size += assembly->sheap.index;
4677         meta_size += assembly->us.index;
4678
4679         for (i=0; i < MONO_TABLE_NUM; ++i)
4680                 meta->tables [i].rows = assembly->tables [i].rows;
4681         
4682         for (i = 0; i < MONO_TABLE_NUM; i++){
4683                 if (meta->tables [i].rows == 0)
4684                         continue;
4685                 valid_mask |= (guint64)1 << i;
4686                 ntables ++;
4687                 meta->tables [i].row_size = mono_metadata_compute_size (
4688                         meta, i, &meta->tables [i].size_bitfield);
4689                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4690         }
4691         heapt_size += 24; /* #~ header size */
4692         heapt_size += ntables * 4;
4693         /* make multiple of 4 */
4694         heapt_size += 3;
4695         heapt_size &= ~3;
4696         meta_size += heapt_size;
4697         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4698         p = (unsigned char*)meta->raw_metadata;
4699         /* the metadata signature */
4700         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4701         /* version numbers and 4 bytes reserved */
4702         int16val = (guint16*)p;
4703         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4704         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4705         p += 8;
4706         /* version string */
4707         int32val = (guint32*)p;
4708         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4709         p += 4;
4710         memcpy (p, meta->version, strlen (meta->version));
4711         p += GUINT32_FROM_LE (*int32val);
4712         align_pointer (meta->raw_metadata, p);
4713         int16val = (guint16*)p;
4714         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4715         *int16val = GUINT16_TO_LE (5); /* number of streams */
4716         p += 4;
4717
4718         /*
4719          * write the stream info.
4720          */
4721         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4722         table_offset += 3; table_offset &= ~3;
4723
4724         assembly->tstream.index = heapt_size;
4725         for (i = 0; i < 5; ++i) {
4726                 int32val = (guint32*)p;
4727                 stream_desc [i].stream->offset = table_offset;
4728                 *int32val++ = GUINT32_TO_LE (table_offset);
4729                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4730                 table_offset += GUINT32_FROM_LE (*int32val);
4731                 table_offset += 3; table_offset &= ~3;
4732                 p += 8;
4733                 strcpy ((char*)p, stream_desc [i].name);
4734                 p += strlen (stream_desc [i].name) + 1;
4735                 align_pointer (meta->raw_metadata, p);
4736         }
4737         /* 
4738          * now copy the data, the table stream header and contents goes first.
4739          */
4740         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4741         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4742         int32val = (guint32*)p;
4743         *int32val = GUINT32_TO_LE (0); /* reserved */
4744         p += 4;
4745
4746         *p++ = 2; /* version */
4747         *p++ = 0;
4748
4749         if (meta->idx_string_wide)
4750                 *p |= 0x01;
4751         if (meta->idx_guid_wide)
4752                 *p |= 0x02;
4753         if (meta->idx_blob_wide)
4754                 *p |= 0x04;
4755         ++p;
4756         *p++ = 1; /* reserved */
4757         int64val = (guint64*)p;
4758         *int64val++ = GUINT64_TO_LE (valid_mask);
4759         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4760         p += 16;
4761         int32val = (guint32*)p;
4762         for (i = 0; i < MONO_TABLE_NUM; i++){
4763                 if (meta->tables [i].rows == 0)
4764                         continue;
4765                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4766         }
4767         p = (unsigned char*)int32val;
4768
4769         /* sort the tables that still need sorting */
4770         table = &assembly->tables [MONO_TABLE_CONSTANT];
4771         if (table->rows)
4772                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4773         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4774         if (table->rows)
4775                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4776         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4777         if (table->rows)
4778                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4779         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4780         if (table->rows)
4781                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4782         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4783         if (table->rows)
4784                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4785         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4786         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4787         if (table->rows)
4788                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4789         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4790         if (table->rows)
4791                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4792
4793         /* compress the tables */
4794         for (i = 0; i < MONO_TABLE_NUM; i++){
4795                 int row, col;
4796                 guint32 *values;
4797                 guint32 bitfield = meta->tables [i].size_bitfield;
4798                 if (!meta->tables [i].rows)
4799                         continue;
4800                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4801                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4802                 meta->tables [i].base = (char*)p;
4803                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4804                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4805                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4806                                 switch (mono_metadata_table_size (bitfield, col)) {
4807                                 case 1:
4808                                         *p++ = values [col];
4809                                         break;
4810                                 case 2:
4811                                         *p++ = values [col] & 0xff;
4812                                         *p++ = (values [col] >> 8) & 0xff;
4813                                         break;
4814                                 case 4:
4815                                         *p++ = values [col] & 0xff;
4816                                         *p++ = (values [col] >> 8) & 0xff;
4817                                         *p++ = (values [col] >> 16) & 0xff;
4818                                         *p++ = (values [col] >> 24) & 0xff;
4819                                         break;
4820                                 default:
4821                                         g_assert_not_reached ();
4822                                 }
4823                         }
4824                 }
4825                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4826         }
4827         
4828         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4829         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4830         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4831         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4832         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4833
4834         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4835
4836         return TRUE;
4837 }
4838
4839 /*
4840  * Some tables in metadata need to be sorted according to some criteria, but
4841  * when methods and fields are first created with reflection, they may be assigned a token
4842  * that doesn't correspond to the final token they will get assigned after the sorting.
4843  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4844  * with the reflection objects that represent them. Once all the tables are set up, the 
4845  * reflection objects will contains the correct table index. fixup_method() will fixup the
4846  * tokens for the method with ILGenerator @ilgen.
4847  */
4848 static void
4849 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4850 {
4851         guint32 code_idx = GPOINTER_TO_UINT (value);
4852         MonoReflectionILTokenInfo *iltoken;
4853         MonoReflectionFieldBuilder *field;
4854         MonoReflectionCtorBuilder *ctor;
4855         MonoReflectionMethodBuilder *method;
4856         MonoReflectionTypeBuilder *tb;
4857         MonoReflectionArrayMethod *am;
4858         guint32 i, idx = 0;
4859         unsigned char *target;
4860
4861         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4862                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4863                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4864                 switch (target [3]) {
4865                 case MONO_TABLE_FIELD:
4866                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4867                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4868                                 idx = field->table_idx;
4869                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4870                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4871                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4872                         } else {
4873                                 g_assert_not_reached ();
4874                         }
4875                         break;
4876                 case MONO_TABLE_METHOD:
4877                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4878                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4879                                 idx = method->table_idx;
4880                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4881                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4882                                 idx = ctor->table_idx;
4883                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4884                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4885                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4886                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4887                         } else {
4888                                 g_assert_not_reached ();
4889                         }
4890                         break;
4891                 case MONO_TABLE_TYPEDEF:
4892                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4893                                 g_assert_not_reached ();
4894                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4895                         idx = tb->table_idx;
4896                         break;
4897                 case MONO_TABLE_MEMBERREF:
4898                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4899                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4900                                 idx = am->table_idx;
4901                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4902                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4903                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4904                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4905                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4906                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4907                                 continue;
4908                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4909                                 continue;
4910                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4911                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4912                                 g_assert (is_field_on_inst (f));
4913                                 continue;
4914                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4915                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4916                                 continue;
4917                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4918                                 continue;
4919                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4920                                 continue;
4921                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4922                                 continue;
4923                         } else {
4924                                 g_assert_not_reached ();
4925                         }
4926                         break;
4927                 case MONO_TABLE_METHODSPEC:
4928                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4929                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4930                                 g_assert (mono_method_signature (m)->generic_param_count);
4931                                 continue;
4932                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4933                                 continue;
4934                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4935                                 continue;
4936                         } else {
4937                                 g_assert_not_reached ();
4938                         }
4939                         break;
4940                 default:
4941                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4942                 }
4943                 target [0] = idx & 0xff;
4944                 target [1] = (idx >> 8) & 0xff;
4945                 target [2] = (idx >> 16) & 0xff;
4946         }
4947 }
4948
4949 /*
4950  * fixup_cattrs:
4951  *
4952  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4953  * value is not known when the table is emitted.
4954  */
4955 static void
4956 fixup_cattrs (MonoDynamicImage *assembly)
4957 {
4958         MonoDynamicTable *table;
4959         guint32 *values;
4960         guint32 type, i, idx, token;
4961         MonoObject *ctor;
4962
4963         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4964
4965         for (i = 0; i < table->rows; ++i) {
4966                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4967
4968                 type = values [MONO_CUSTOM_ATTR_TYPE];
4969                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4970                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4971                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4972                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4973                         g_assert (ctor);
4974
4975                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4976                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4977                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4978                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4979                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4980                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4981                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4982                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4983                         }
4984                 }
4985         }
4986 }
4987
4988 static gboolean
4989 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
4990 {
4991         MonoDynamicTable *table;
4992         guint32 *values;
4993
4994         mono_error_init (error);
4995
4996         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4997         table->rows++;
4998         alloc_table (table, table->rows);
4999         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
5000         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
5001         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
5002         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
5003         return_val_if_nok (error, FALSE);
5004         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
5005         table->next_idx++;
5006         return TRUE;
5007 }
5008
5009 static gboolean
5010 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
5011 {
5012         MonoDynamicTable *table;
5013         guint32 *values;
5014         char blob_size [6];
5015         guchar hash [20];
5016         char *b = blob_size;
5017         char *name, *sname;
5018         guint32 idx, offset;
5019
5020         mono_error_init (error);
5021
5022         if (rsrc->filename) {
5023                 name = mono_string_to_utf8_checked (rsrc->filename, error);
5024                 return_val_if_nok (error, FALSE);
5025                 sname = g_path_get_basename (name);
5026         
5027                 table = &assembly->tables [MONO_TABLE_FILE];
5028                 table->rows++;
5029                 alloc_table (table, table->rows);
5030                 values = table->values + table->next_idx * MONO_FILE_SIZE;
5031                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
5032                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
5033                 g_free (sname);
5034
5035                 mono_sha1_get_digest_from_file (name, hash);
5036                 mono_metadata_encode_value (20, b, &b);
5037                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
5038                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
5039                 g_free (name);
5040                 idx = table->next_idx++;
5041                 rsrc->offset = 0;
5042                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
5043         } else {
5044                 char sizebuf [4];
5045                 char *data;
5046                 guint len;
5047                 if (rsrc->data) {
5048                         data = mono_array_addr (rsrc->data, char, 0);
5049                         len = mono_array_length (rsrc->data);
5050                 } else {
5051                         data = NULL;
5052                         len = 0;
5053                 }
5054                 offset = len;
5055                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
5056                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
5057                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
5058                 mono_image_add_stream_data (&assembly->resources, data, len);
5059
5060                 if (!mb->is_main)
5061                         /* 
5062                          * The entry should be emitted into the MANIFESTRESOURCE table of 
5063                          * the main module, but that needs to reference the FILE table
5064                          * which isn't emitted yet.
5065                          */
5066                         return TRUE;
5067                 else
5068                         idx = 0;
5069         }
5070
5071         return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
5072 }
5073
5074 static gboolean
5075 set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
5076 {
5077         gchar *ver, *p, *str;
5078         guint32 i;
5079         
5080         mono_error_init (error);
5081
5082         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5083         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5084         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5085         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5086         if (!version)
5087                 return TRUE;
5088         ver = str = mono_string_to_utf8_checked (version, error);
5089         return_val_if_nok (error, FALSE);
5090         for (i = 0; i < 4; ++i) {
5091                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5092                 switch (*p) {
5093                 case '.':
5094                         p++;
5095                         break;
5096                 case '*':
5097                         /* handle Revision and Build */
5098                         p++;
5099                         break;
5100                 }
5101                 ver = p;
5102         }
5103         g_free (str);
5104         return TRUE;
5105 }
5106
5107 static guint32
5108 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5109         gsize len;
5110         guint32 token = 0;
5111         char blob_size [6];
5112         char *b = blob_size;
5113
5114         if (!pkey)
5115                 return token;
5116
5117         len = mono_array_length (pkey);
5118         mono_metadata_encode_value (len, b, &b);
5119         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5120         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5121
5122         assembly->public_key = (guint8 *)g_malloc (len);
5123         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5124         assembly->public_key_len = len;
5125
5126         /* Special case: check for ECMA key (16 bytes) */
5127         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5128                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5129                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5130         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5131                 /* minimum key size (in 2.0) is 384 bits */
5132                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5133         } else {
5134                 /* FIXME - verifier */
5135                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5136                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5137         }
5138         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5139
5140         return token;
5141 }
5142
5143 static gboolean
5144 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5145 {
5146         MonoDynamicTable *table;
5147         MonoDynamicImage *assembly;
5148         MonoReflectionAssemblyBuilder *assemblyb;
5149         MonoDomain *domain;
5150         guint32 *values;
5151         int i;
5152         guint32 module_index;
5153
5154         mono_error_init (error);
5155
5156         assemblyb = moduleb->assemblyb;
5157         assembly = moduleb->dynamic_image;
5158         domain = mono_object_domain (assemblyb);
5159
5160         /* Emit ASSEMBLY table */
5161         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5162         alloc_table (table, 1);
5163         values = table->values + MONO_ASSEMBLY_SIZE;
5164         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5165         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
5166         return_val_if_nok (error, FALSE);
5167         if (assemblyb->culture) {
5168                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
5169                 return_val_if_nok (error, FALSE);
5170         } else {
5171                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5172         }
5173         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5174         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5175         if (!set_version_from_string (assemblyb->version, values, error))
5176                 return FALSE;
5177
5178         /* Emit FILE + EXPORTED_TYPE table */
5179         module_index = 0;
5180         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5181                 int j;
5182                 MonoReflectionModuleBuilder *file_module = 
5183                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5184                 if (file_module != moduleb) {
5185                         if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
5186                                 return FALSE;
5187                         module_index ++;
5188                         if (file_module->types) {
5189                                 for (j = 0; j < file_module->num_types; ++j) {
5190                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5191                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5192                                         return_val_if_nok (error, FALSE);
5193                                 }
5194                         }
5195                 }
5196         }
5197         if (assemblyb->loaded_modules) {
5198                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5199                         MonoReflectionModule *file_module = 
5200                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5201                         if (!mono_image_fill_file_table (domain, file_module, assembly, error))
5202                                 return FALSE;
5203                         module_index ++;
5204                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5205                 }
5206         }
5207         if (assemblyb->type_forwarders)
5208                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5209
5210         /* Emit MANIFESTRESOURCE table */
5211         module_index = 0;
5212         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5213                 int j;
5214                 MonoReflectionModuleBuilder *file_module = 
5215                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5216                 /* The table for the main module is emitted later */
5217                 if (file_module != moduleb) {
5218                         module_index ++;
5219                         if (file_module->resources) {
5220                                 int len = mono_array_length (file_module->resources);
5221                                 for (j = 0; j < len; ++j) {
5222                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5223                                         if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
5224                                                 return FALSE;
5225                                 }
5226                         }
5227                 }
5228         }
5229         return TRUE;
5230 }
5231
5232 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5233
5234 /*
5235  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5236  * for the modulebuilder @moduleb.
5237  * At the end of the process, method and field tokens are fixed up and the 
5238  * on-disk compressed metadata representation is created.
5239  * Return TRUE on success, or FALSE on failure and sets @error
5240  */
5241 gboolean
5242 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5243 {
5244         MonoDynamicTable *table;
5245         MonoDynamicImage *assembly;
5246         MonoReflectionAssemblyBuilder *assemblyb;
5247         MonoDomain *domain;
5248         MonoPtrArray types;
5249         guint32 *values;
5250         int i, j;
5251
5252         mono_error_init (error);
5253
5254         assemblyb = moduleb->assemblyb;
5255         assembly = moduleb->dynamic_image;
5256         domain = mono_object_domain (assemblyb);
5257
5258         if (assembly->text_rva)
5259                 return TRUE;
5260
5261         assembly->text_rva = START_TEXT_RVA;
5262
5263         if (moduleb->is_main) {
5264                 mono_image_emit_manifest (moduleb, error);
5265                 return_val_if_nok (error, FALSE);
5266         }
5267
5268         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5269         table->rows = 1; /* .<Module> */
5270         table->next_idx++;
5271         alloc_table (table, table->rows);
5272         /*
5273          * Set the first entry.
5274          */
5275         values = table->values + table->columns;
5276         values [MONO_TYPEDEF_FLAGS] = 0;
5277         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5278         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5279         values [MONO_TYPEDEF_EXTENDS] = 0;
5280         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5281         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5282
5283         /* 
5284          * handle global methods 
5285          * FIXME: test what to do when global methods are defined in multiple modules.
5286          */
5287         if (moduleb->global_methods) {
5288                 table = &assembly->tables [MONO_TABLE_METHOD];
5289                 table->rows += mono_array_length (moduleb->global_methods);
5290                 alloc_table (table, table->rows);
5291                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5292                         if (!mono_image_get_method_info (
5293                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5294                                 goto leave;
5295                 }
5296         }
5297         if (moduleb->global_fields) {
5298                 table = &assembly->tables [MONO_TABLE_FIELD];
5299                 table->rows += mono_array_length (moduleb->global_fields);
5300                 alloc_table (table, table->rows);
5301                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5302                         mono_image_get_field_info (
5303                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5304                                 error);
5305                         if (!is_ok (error))
5306                                 goto leave;
5307                 }
5308         }
5309
5310         table = &assembly->tables [MONO_TABLE_MODULE];
5311         alloc_table (table, 1);
5312         mono_image_fill_module_table (domain, moduleb, assembly, error);
5313         if (!is_ok (error))
5314                 goto leave;
5315
5316         /* Collect all types into a list sorted by their table_idx */
5317         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5318
5319         if (moduleb->types)
5320                 for (i = 0; i < moduleb->num_types; ++i) {
5321                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5322                         collect_types (&types, type);
5323                 }
5324
5325         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5326         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5327         table->rows += mono_ptr_array_size (types);
5328         alloc_table (table, table->rows);
5329
5330         /*
5331          * Emit type names + namespaces at one place inside the string heap,
5332          * so load_class_names () needs to touch fewer pages.
5333          */
5334         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5335                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5336                 string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
5337                 if (!is_ok (error))
5338                         goto leave_types;
5339         }
5340         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5341                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5342                 string_heap_insert_mstring (&assembly->sheap, tb->name, error);
5343                 if (!is_ok (error))
5344                         goto leave_types;
5345         }
5346
5347         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5348                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5349                 if (!mono_image_get_type_info (domain, type, assembly, error))
5350                         goto leave_types;
5351         }
5352
5353         /* 
5354          * table->rows is already set above and in mono_image_fill_module_table.
5355          */
5356         /* add all the custom attributes at the end, once all the indexes are stable */
5357         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5358                 goto leave_types;
5359
5360         /* CAS assembly permissions */
5361         if (assemblyb->permissions_minimum)
5362                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5363         if (assemblyb->permissions_optional)
5364                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5365         if (assemblyb->permissions_refused)
5366                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5367
5368         if (!module_add_cattrs (assembly, moduleb, error))
5369                 goto leave_types;
5370
5371         /* fixup tokens */
5372         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5373
5374         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5375          * the final tokens and don't need another fixup pass. */
5376
5377         if (moduleb->global_methods) {
5378                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5379                         MonoReflectionMethodBuilder *mb = mono_array_get (
5380                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5381                         if (!mono_image_add_methodimpl (assembly, mb, error))
5382                                 goto leave_types;
5383                 }
5384         }
5385
5386         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5387                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5388                 if (type->methods) {
5389                         for (j = 0; j < type->num_methods; ++j) {
5390                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5391                                         type->methods, MonoReflectionMethodBuilder*, j);
5392
5393                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5394                                         goto leave_types;
5395                         }
5396                 }
5397         }
5398
5399         fixup_cattrs (assembly);
5400
5401 leave_types:
5402         mono_ptr_array_destroy (types);
5403 leave:
5404
5405         return mono_error_ok (error);
5406 }
5407
5408 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5409
5410 gboolean
5411 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5412 {
5413         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5414 }
5415
5416 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5417
5418
5419 typedef struct {
5420         guint32 import_lookup_table;
5421         guint32 timestamp;
5422         guint32 forwarder;
5423         guint32 name_rva;
5424         guint32 import_address_table_rva;
5425 } MonoIDT;
5426
5427 typedef struct {
5428         guint32 name_rva;
5429         guint32 flags;
5430 } MonoILT;
5431
5432 #ifndef DISABLE_REFLECTION_EMIT
5433
5434 /*
5435  * mono_image_insert_string:
5436  * @module: module builder object
5437  * @str: a string
5438  *
5439  * Insert @str into the user string stream of @module.
5440  */
5441 guint32
5442 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5443 {
5444         MonoDynamicImage *assembly;
5445         guint32 idx;
5446         char buf [16];
5447         char *b = buf;
5448         
5449         if (!module->dynamic_image)
5450                 mono_image_module_basic_init (module);
5451
5452         assembly = module->dynamic_image;
5453         
5454         if (assembly->save) {
5455                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5456                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5457 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5458         {
5459                 char *swapped = g_malloc (2 * mono_string_length (str));
5460                 const char *p = (const char*)mono_string_chars (str);
5461
5462                 swap_with_size (swapped, p, 2, mono_string_length (str));
5463                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5464                 g_free (swapped);
5465         }
5466 #else
5467                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5468 #endif
5469                 mono_image_add_stream_data (&assembly->us, "", 1);
5470         } else {
5471                 idx = assembly->us.index ++;
5472         }
5473
5474         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5475
5476         return MONO_TOKEN_STRING | idx;
5477 }
5478
5479 guint32
5480 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5481 {
5482         MonoClass *klass;
5483         guint32 token = 0;
5484         MonoMethodSignature *sig;
5485
5486         mono_error_init (error);
5487
5488         klass = obj->vtable->klass;
5489         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5490                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5491                 MonoMethodSignature *old;
5492                 guint32 sig_token, parent;
5493                 int nargs, i;
5494
5495                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5496
5497                 nargs = mono_array_length (opt_param_types);
5498                 old = mono_method_signature (method);
5499                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5500
5501                 sig->hasthis = old->hasthis;
5502                 sig->explicit_this = old->explicit_this;
5503                 sig->call_convention = old->call_convention;
5504                 sig->generic_param_count = old->generic_param_count;
5505                 sig->param_count = old->param_count + nargs;
5506                 sig->sentinelpos = old->param_count;
5507                 sig->ret = old->ret;
5508
5509                 for (i = 0; i < old->param_count; i++)
5510                         sig->params [i] = old->params [i];
5511
5512                 for (i = 0; i < nargs; i++) {
5513                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5514                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5515                         if (!is_ok (error)) goto fail;
5516                 }
5517
5518                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5519                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5520                 parent >>= MONO_TYPEDEFORREF_BITS;
5521
5522                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5523                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5524
5525                 sig_token = method_encode_signature (assembly, sig);
5526                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5527         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5528                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5529                 ReflectionMethodBuilder rmb;
5530                 guint32 parent, sig_token;
5531                 int nopt_args, nparams, ngparams, i;
5532
5533                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5534                         goto fail;
5535                 
5536                 rmb.opt_types = opt_param_types;
5537                 nopt_args = mono_array_length (opt_param_types);
5538
5539                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5540                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5541                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5542
5543                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5544                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5545                 sig->call_convention = rmb.call_conv;
5546                 sig->generic_param_count = ngparams;
5547                 sig->param_count = nparams + nopt_args;
5548                 sig->sentinelpos = nparams;
5549                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5550                 if (!is_ok (error)) goto fail;
5551
5552                 for (i = 0; i < nparams; i++) {
5553                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5554                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5555                         if (!is_ok (error)) goto fail;
5556                 }
5557
5558                 for (i = 0; i < nopt_args; i++) {
5559                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5560                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5561                         if (!is_ok (error)) goto fail;
5562                 }
5563
5564                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5565                 if (!is_ok (error))
5566                         goto fail;
5567
5568                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5569                 if (!mono_error_ok (error))
5570                         goto fail;
5571                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5572
5573                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5574                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5575
5576                 char *name = mono_string_to_utf8_checked (rmb.name, error);
5577                 if (!is_ok (error)) goto fail;
5578                 token = mono_image_get_varargs_method_token (
5579                         assembly, parent, name, sig_token);
5580                 g_free (name);
5581         } else {
5582                 g_error ("requested method token for %s\n", klass->name);
5583         }
5584
5585         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5586         register_dyn_token (assembly, token, obj);
5587         return token;
5588 fail:
5589         g_assert (!mono_error_ok (error));
5590         return 0;
5591 }
5592
5593 /*
5594  * mono_image_create_token:
5595  * @assembly: a dynamic assembly
5596  * @obj:
5597  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5598  *
5599  * Get a token to insert in the IL code stream for the given MemberInfo.
5600  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5601  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5602  * entry.
5603  */
5604 guint32
5605 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5606                          gboolean create_open_instance, gboolean register_token,
5607                          MonoError *error)
5608 {
5609         MonoClass *klass;
5610         guint32 token = 0;
5611
5612         mono_error_init (error);
5613
5614         klass = obj->vtable->klass;
5615
5616         /* Check for user defined reflection objects */
5617         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5618         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5619                 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5620                 return 0;
5621         }
5622
5623         if (strcmp (klass->name, "MethodBuilder") == 0) {
5624                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5625                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5626
5627                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5628                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5629                 else {
5630                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5631                         if (!mono_error_ok (error))
5632                                 return 0;
5633                 }
5634                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5635         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5636                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5637                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5638
5639                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5640                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5641                 else {
5642                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5643                         if (!mono_error_ok (error))
5644                                 return 0;
5645                 }
5646                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5647         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5648                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5649                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5650                 if (tb->generic_params) {
5651                         token = mono_image_get_generic_field_token (assembly, fb, error);
5652                         return_val_if_nok (error, 0);
5653                 } else {
5654                         if (tb->module->dynamic_image == assembly) {
5655                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5656                         } else {
5657                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5658                         }
5659                 }
5660         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5661                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5662                 if (create_open_instance && tb->generic_params) {
5663                         MonoType *type;
5664                         init_type_builder_generics (obj, error);
5665                         return_val_if_nok (error, 0);
5666                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5667                         return_val_if_nok (error, 0);
5668                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5669                         token = mono_metadata_token_from_dor (token);
5670                 } else if (tb->module->dynamic_image == assembly) {
5671                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5672                 } else {
5673                         MonoType *type;
5674                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5675                         return_val_if_nok (error, 0);
5676                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5677                 }
5678         } else if (strcmp (klass->name, "RuntimeType") == 0) {
5679                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5680                 return_val_if_nok (error, 0);
5681                 MonoClass *mc = mono_class_from_mono_type (type);
5682                 token = mono_metadata_token_from_dor (
5683                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5684         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5685                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5686                 return_val_if_nok (error, 0);
5687                 token = mono_metadata_token_from_dor (
5688                         mono_image_typedef_or_ref (assembly, type));
5689         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5690                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5691                 return_val_if_nok (error, 0);
5692                 token = mono_metadata_token_from_dor (
5693                         mono_image_typedef_or_ref (assembly, type));
5694         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5695                    strcmp (klass->name, "MonoMethod") == 0 ||
5696                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5697                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5698                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5699                 if (m->method->is_inflated) {
5700                         if (create_open_instance)
5701                                 token = mono_image_get_methodspec_token (assembly, m->method);
5702                         else
5703                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5704                 } else if ((m->method->klass->image == &assembly->image) &&
5705                          !m->method->klass->generic_class) {
5706                         static guint32 method_table_idx = 0xffffff;
5707                         if (m->method->klass->wastypebuilder) {
5708                                 /* we use the same token as the one that was assigned
5709                                  * to the Methodbuilder.
5710                                  * FIXME: do the equivalent for Fields.
5711                                  */
5712                                 token = m->method->token;
5713                         } else {
5714                                 /*
5715                                  * Each token should have a unique index, but the indexes are
5716                                  * assigned by managed code, so we don't know about them. An
5717                                  * easy solution is to count backwards...
5718                                  */
5719                                 method_table_idx --;
5720                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5721                         }
5722                 } else {
5723                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5724                 }
5725                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5726         } else if (strcmp (klass->name, "MonoField") == 0) {
5727                 MonoReflectionField *f = (MonoReflectionField *)obj;
5728                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5729                         static guint32 field_table_idx = 0xffffff;
5730                         field_table_idx --;
5731                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5732                 } else {
5733                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5734                 }
5735                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5736         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5737                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5738                 token = mono_image_get_array_token (assembly, m, error);
5739                 return_val_if_nok (error, 0);
5740         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5741                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5742                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5743                 return_val_if_nok (error, 0);
5744         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5745                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5746                 return_val_if_nok (error, 0);
5747                 token = mono_metadata_token_from_dor (
5748                         mono_image_typedef_or_ref (assembly, type));
5749         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5750                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5751                 token = mono_image_get_field_on_inst_token (assembly, f, error);
5752                 return_val_if_nok (error, 0);
5753         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5754                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5755                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5756                 if (!mono_error_ok (error))
5757                         return 0;
5758         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5759                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5760                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5761                 if (!mono_error_ok (error))
5762                         return 0;
5763         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5764                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5765                 return_val_if_nok (error, 0);
5766                 token = mono_metadata_token_from_dor (
5767                                 mono_image_typedef_or_ref (assembly, type));
5768         } else {
5769                 g_error ("requested token for %s\n", klass->name);
5770         }
5771
5772         if (register_token)
5773                 mono_image_register_token (assembly, token, obj);
5774
5775         return token;
5776 }
5777
5778 /*
5779  * mono_image_register_token:
5780  *
5781  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5782  * the Module.ResolveXXXToken () methods to work.
5783  */
5784 void
5785 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5786 {
5787         MonoObject *prev;
5788
5789         dynamic_image_lock (assembly);
5790         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5791         if (prev) {
5792                 /* There could be multiple MethodInfo objects with the same token */
5793                 //g_assert (prev == obj);
5794         } else {
5795                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5796         }
5797         dynamic_image_unlock (assembly);
5798 }
5799
5800 static MonoDynamicImage*
5801 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5802 {
5803         static const guchar entrycode [16] = {0xff, 0x25, 0};
5804         MonoDynamicImage *image;
5805         int i;
5806
5807         const char *version;
5808
5809         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5810                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5811         else
5812                 version = mono_get_runtime_info ()->runtime_version;
5813
5814 #if HAVE_BOEHM_GC
5815         /* The MonoGHashTable's need GC tracking */
5816         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5817 #else
5818         image = g_new0 (MonoDynamicImage, 1);
5819 #endif
5820
5821         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5822         
5823         /*g_print ("created image %p\n", image);*/
5824         /* keep in sync with image.c */
5825         image->image.name = assembly_name;
5826         image->image.assembly_name = image->image.name; /* they may be different */
5827         image->image.module_name = module_name;
5828         image->image.version = g_strdup (version);
5829         image->image.md_version_major = 1;
5830         image->image.md_version_minor = 1;
5831         image->image.dynamic = TRUE;
5832
5833         image->image.references = g_new0 (MonoAssembly*, 1);
5834         image->image.references [0] = NULL;
5835
5836         mono_image_init (&image->image);
5837
5838         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");
5839         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5840         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5841         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5842         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5843         image->handleref = g_hash_table_new (NULL, NULL);
5844         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");
5845         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5846         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");
5847         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");
5848         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5849         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5850         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5851         image->gen_params = g_ptr_array_new ();
5852         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5853
5854         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5855         string_heap_init (&image->sheap);
5856         mono_image_add_stream_data (&image->us, "", 1);
5857         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5858         /* import tables... */
5859         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5860         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5861         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5862         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5863         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5864         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5865         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5866         stream_data_align (&image->code);
5867
5868         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5869
5870         for (i=0; i < MONO_TABLE_NUM; ++i) {
5871                 image->tables [i].next_idx = 1;
5872                 image->tables [i].columns = table_sizes [i];
5873         }
5874
5875         image->image.assembly = (MonoAssembly*)assembly;
5876         image->run = assembly->run;
5877         image->save = assembly->save;
5878         image->pe_kind = 0x1; /* ILOnly */
5879         image->machine = 0x14c; /* I386 */
5880         
5881         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5882
5883         dynamic_images_lock ();
5884
5885         if (!dynamic_images)
5886                 dynamic_images = g_ptr_array_new ();
5887
5888         g_ptr_array_add (dynamic_images, image);
5889
5890         dynamic_images_unlock ();
5891
5892         return image;
5893 }
5894 #endif
5895
5896 static void
5897 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5898 {
5899         g_free (key);
5900 }
5901
5902 static void
5903 release_hashtable (MonoGHashTable **hash)
5904 {
5905         if (*hash) {
5906                 mono_g_hash_table_destroy (*hash);
5907                 *hash = NULL;
5908         }
5909 }
5910
5911 void
5912 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5913 {
5914         release_hashtable (&image->token_fixups);
5915         release_hashtable (&image->handleref_managed);
5916         release_hashtable (&image->tokens);
5917         release_hashtable (&image->remapped_tokens);
5918         release_hashtable (&image->generic_def_objects);
5919         release_hashtable (&image->methodspec);
5920 }
5921
5922 // Free dynamic image pass one: Free resources but not image itself
5923 void
5924 mono_dynamic_image_free (MonoDynamicImage *image)
5925 {
5926         MonoDynamicImage *di = image;
5927         GList *list;
5928         int i;
5929
5930         if (di->methodspec)
5931                 mono_g_hash_table_destroy (di->methodspec);
5932         if (di->typespec)
5933                 g_hash_table_destroy (di->typespec);
5934         if (di->typeref)
5935                 g_hash_table_destroy (di->typeref);
5936         if (di->handleref)
5937                 g_hash_table_destroy (di->handleref);
5938         if (di->handleref_managed)
5939                 mono_g_hash_table_destroy (di->handleref_managed);
5940         if (di->tokens)
5941                 mono_g_hash_table_destroy (di->tokens);
5942         if (di->remapped_tokens)
5943                 mono_g_hash_table_destroy (di->remapped_tokens);
5944         if (di->generic_def_objects)
5945                 mono_g_hash_table_destroy (di->generic_def_objects);
5946         if (di->blob_cache) {
5947                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5948                 g_hash_table_destroy (di->blob_cache);
5949         }
5950         if (di->standalonesig_cache)
5951                 g_hash_table_destroy (di->standalonesig_cache);
5952         for (list = di->array_methods; list; list = list->next) {
5953                 ArrayMethod *am = (ArrayMethod *)list->data;
5954                 g_free (am->sig);
5955                 g_free (am->name);
5956                 g_free (am);
5957         }
5958         g_list_free (di->array_methods);
5959         if (di->gen_params) {
5960                 for (i = 0; i < di->gen_params->len; i++) {
5961                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5962                         mono_gc_deregister_root ((char*) &entry->gparam);
5963                         g_free (entry);
5964                 }
5965                 g_ptr_array_free (di->gen_params, TRUE);
5966         }
5967         if (di->token_fixups)
5968                 mono_g_hash_table_destroy (di->token_fixups);
5969         if (di->method_to_table_idx)
5970                 g_hash_table_destroy (di->method_to_table_idx);
5971         if (di->field_to_table_idx)
5972                 g_hash_table_destroy (di->field_to_table_idx);
5973         if (di->method_aux_hash)
5974                 g_hash_table_destroy (di->method_aux_hash);
5975         if (di->vararg_aux_hash)
5976                 g_hash_table_destroy (di->vararg_aux_hash);
5977         g_free (di->strong_name);
5978         g_free (di->win32_res);
5979         if (di->public_key)
5980                 g_free (di->public_key);
5981
5982         /*g_print ("string heap destroy for image %p\n", di);*/
5983         mono_dynamic_stream_reset (&di->sheap);
5984         mono_dynamic_stream_reset (&di->code);
5985         mono_dynamic_stream_reset (&di->resources);
5986         mono_dynamic_stream_reset (&di->us);
5987         mono_dynamic_stream_reset (&di->blob);
5988         mono_dynamic_stream_reset (&di->tstream);
5989         mono_dynamic_stream_reset (&di->guid);
5990         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5991                 g_free (di->tables [i].values);
5992         }
5993
5994         dynamic_images_lock ();
5995
5996         if (dynamic_images)
5997                 g_ptr_array_remove (dynamic_images, di);
5998
5999         dynamic_images_unlock ();
6000 }
6001
6002 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
6003 void
6004 mono_dynamic_image_free_image (MonoDynamicImage *image)
6005 {
6006         /* See create_dynamic_mono_image () */
6007 #if HAVE_BOEHM_GC
6008         /* Allocated using GC_MALLOC */
6009 #else
6010         g_free (image);
6011 #endif
6012 }
6013
6014 #ifndef DISABLE_REFLECTION_EMIT
6015
6016 /*
6017  * mono_image_basic_init:
6018  * @assembly: an assembly builder object
6019  *
6020  * Create the MonoImage that represents the assembly builder and setup some
6021  * of the helper hash table and the basic metadata streams.
6022  */
6023 void
6024 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
6025 {
6026         MonoError error;
6027         MonoDynamicAssembly *assembly;
6028         MonoDynamicImage *image;
6029         MonoDomain *domain = mono_object_domain (assemblyb);
6030         
6031         if (assemblyb->dynamic_assembly)
6032                 return;
6033
6034 #if HAVE_BOEHM_GC
6035         /* assembly->assembly.image might be GC allocated */
6036         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
6037 #else
6038         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
6039 #endif
6040
6041         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
6042         
6043         assembly->assembly.ref_count = 1;
6044         assembly->assembly.dynamic = TRUE;
6045         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
6046         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
6047         assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
6048         if (mono_error_set_pending_exception (&error))
6049                 return;
6050         if (assemblyb->culture) {
6051                 assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
6052                 if (mono_error_set_pending_exception (&error))
6053                         return;
6054         } else
6055                 assembly->assembly.aname.culture = g_strdup ("");
6056
6057         if (assemblyb->version) {
6058                         char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
6059                         if (mono_error_set_pending_exception (&error))
6060                                 return;
6061                         char **version = g_strsplit (vstr, ".", 4);
6062                         char **parts = version;
6063                         assembly->assembly.aname.major = atoi (*parts++);
6064                         assembly->assembly.aname.minor = atoi (*parts++);
6065                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
6066                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
6067
6068                         g_strfreev (version);
6069                         g_free (vstr);
6070         } else {
6071                         assembly->assembly.aname.major = 0;
6072                         assembly->assembly.aname.minor = 0;
6073                         assembly->assembly.aname.build = 0;
6074                         assembly->assembly.aname.revision = 0;
6075         }
6076
6077         assembly->run = assemblyb->access != 2;
6078         assembly->save = assemblyb->access != 1;
6079         assembly->domain = domain;
6080
6081         char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
6082         if (mono_error_set_pending_exception (&error))
6083                 return;
6084         image = create_dynamic_mono_image (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
6085         image->initial_image = TRUE;
6086         assembly->assembly.aname.name = image->image.name;
6087         assembly->assembly.image = &image->image;
6088         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
6089                 /* -1 to correct for the trailing NULL byte */
6090                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
6091                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6092                 }
6093                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
6094         }
6095
6096         mono_domain_assemblies_lock (domain);
6097         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6098         mono_domain_assemblies_unlock (domain);
6099
6100         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6101         
6102         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6103         
6104         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6105 }
6106
6107 #endif /* !DISABLE_REFLECTION_EMIT */
6108
6109 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6110
6111 static int
6112 calc_section_size (MonoDynamicImage *assembly)
6113 {
6114         int nsections = 0;
6115
6116         /* alignment constraints */
6117         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6118         g_assert ((assembly->code.index % 4) == 0);
6119         assembly->meta_size += 3;
6120         assembly->meta_size &= ~3;
6121         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6122         g_assert ((assembly->resources.index % 4) == 0);
6123
6124         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6125         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6126         nsections++;
6127
6128         if (assembly->win32_res) {
6129                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6130
6131                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6132                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6133                 nsections++;
6134         }
6135
6136         assembly->sections [MONO_SECTION_RELOC].size = 12;
6137         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6138         nsections++;
6139
6140         return nsections;
6141 }
6142
6143 typedef struct {
6144         guint32 id;
6145         guint32 offset;
6146         GSList *children;
6147         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6148 } ResTreeNode;
6149
6150 static int
6151 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6152 {
6153         ResTreeNode *t1 = (ResTreeNode*)a;
6154         ResTreeNode *t2 = (ResTreeNode*)b;
6155
6156         return t1->id - t2->id;
6157 }
6158
6159 /*
6160  * resource_tree_create:
6161  *
6162  *  Organize the resources into a resource tree.
6163  */
6164 static ResTreeNode *
6165 resource_tree_create (MonoArray *win32_resources)
6166 {
6167         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6168         GSList *l;
6169         int i;
6170
6171         tree = g_new0 (ResTreeNode, 1);
6172         
6173         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6174                 MonoReflectionWin32Resource *win32_res =
6175                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6176
6177                 /* Create node */
6178
6179                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6180                 lang_node = g_new0 (ResTreeNode, 1);
6181                 lang_node->id = win32_res->lang_id;
6182                 lang_node->win32_res = win32_res;
6183
6184                 /* Create type node if neccesary */
6185                 type_node = NULL;
6186                 for (l = tree->children; l; l = l->next)
6187                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6188                                 type_node = (ResTreeNode*)l->data;
6189                                 break;
6190                         }
6191
6192                 if (!type_node) {
6193                         type_node = g_new0 (ResTreeNode, 1);
6194                         type_node->id = win32_res->res_type;
6195
6196                         /* 
6197                          * The resource types have to be sorted otherwise
6198                          * Windows Explorer can't display the version information.
6199                          */
6200                         tree->children = g_slist_insert_sorted (tree->children, 
6201                                 type_node, resource_tree_compare_by_id);
6202                 }
6203
6204                 /* Create res node if neccesary */
6205                 res_node = NULL;
6206                 for (l = type_node->children; l; l = l->next)
6207                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6208                                 res_node = (ResTreeNode*)l->data;
6209                                 break;
6210                         }
6211
6212                 if (!res_node) {
6213                         res_node = g_new0 (ResTreeNode, 1);
6214                         res_node->id = win32_res->res_id;
6215                         type_node->children = g_slist_append (type_node->children, res_node);
6216                 }
6217
6218                 res_node->children = g_slist_append (res_node->children, lang_node);
6219         }
6220
6221         return tree;
6222 }
6223
6224 /*
6225  * resource_tree_encode:
6226  * 
6227  *   Encode the resource tree into the format used in the PE file.
6228  */
6229 static void
6230 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6231 {
6232         char *entries;
6233         MonoPEResourceDir dir;
6234         MonoPEResourceDirEntry dir_entry;
6235         MonoPEResourceDataEntry data_entry;
6236         GSList *l;
6237         guint32 res_id_entries;
6238
6239         /*
6240          * For the format of the resource directory, see the article
6241          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6242          * Matt Pietrek
6243          */
6244
6245         memset (&dir, 0, sizeof (dir));
6246         memset (&dir_entry, 0, sizeof (dir_entry));
6247         memset (&data_entry, 0, sizeof (data_entry));
6248
6249         g_assert (sizeof (dir) == 16);
6250         g_assert (sizeof (dir_entry) == 8);
6251         g_assert (sizeof (data_entry) == 16);
6252
6253         node->offset = p - begin;
6254
6255         /* IMAGE_RESOURCE_DIRECTORY */
6256         res_id_entries = g_slist_length (node->children);
6257         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6258
6259         memcpy (p, &dir, sizeof (dir));
6260         p += sizeof (dir);
6261
6262         /* Reserve space for entries */
6263         entries = p;
6264         p += sizeof (dir_entry) * res_id_entries;
6265
6266         /* Write children */
6267         for (l = node->children; l; l = l->next) {
6268                 ResTreeNode *child = (ResTreeNode*)l->data;
6269
6270                 if (child->win32_res) {
6271                         guint32 size;
6272
6273                         child->offset = p - begin;
6274
6275                         /* IMAGE_RESOURCE_DATA_ENTRY */
6276                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6277                         size = mono_array_length (child->win32_res->res_data);
6278                         data_entry.rde_size = GUINT32_TO_LE (size);
6279
6280                         memcpy (p, &data_entry, sizeof (data_entry));
6281                         p += sizeof (data_entry);
6282
6283                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6284                         p += size;
6285                 } else {
6286                         resource_tree_encode (child, begin, p, &p);
6287                 }
6288         }
6289
6290         /* IMAGE_RESOURCE_ENTRY */
6291         for (l = node->children; l; l = l->next) {
6292                 ResTreeNode *child = (ResTreeNode*)l->data;
6293
6294                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6295                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6296
6297                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6298                 entries += sizeof (dir_entry);
6299         }
6300
6301         *endbuf = p;
6302 }
6303
6304 static void
6305 resource_tree_free (ResTreeNode * node)
6306 {
6307         GSList * list;
6308         for (list = node->children; list; list = list->next)
6309                 resource_tree_free ((ResTreeNode*)list->data);
6310         g_slist_free(node->children);
6311         g_free (node);
6312 }
6313
6314 static void
6315 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6316 {
6317         char *buf;
6318         char *p;
6319         guint32 size, i;
6320         MonoReflectionWin32Resource *win32_res;
6321         ResTreeNode *tree;
6322
6323         if (!assemblyb->win32_resources)
6324                 return;
6325
6326         /*
6327          * Resources are stored in a three level tree inside the PE file.
6328          * - level one contains a node for each type of resource
6329          * - level two contains a node for each resource
6330          * - level three contains a node for each instance of a resource for a
6331          *   specific language.
6332          */
6333
6334         tree = resource_tree_create (assemblyb->win32_resources);
6335
6336         /* Estimate the size of the encoded tree */
6337         size = 0;
6338         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6339                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6340                 size += mono_array_length (win32_res->res_data);
6341         }
6342         /* Directory structure */
6343         size += mono_array_length (assemblyb->win32_resources) * 256;
6344         p = buf = (char *)g_malloc (size);
6345
6346         resource_tree_encode (tree, p, p, &p);
6347
6348         g_assert (p - buf <= size);
6349
6350         assembly->win32_res = (char *)g_malloc (p - buf);
6351         assembly->win32_res_size = p - buf;
6352         memcpy (assembly->win32_res, buf, p - buf);
6353
6354         g_free (buf);
6355         resource_tree_free (tree);
6356 }
6357
6358 static void
6359 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6360 {
6361         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6362         int i;
6363
6364         p += sizeof (MonoPEResourceDir);
6365         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6366                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6367                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6368                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6369                         fixup_resource_directory (res_section, child, rva);
6370                 } else {
6371                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6372                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6373                 }
6374
6375                 p += sizeof (MonoPEResourceDirEntry);
6376         }
6377 }
6378
6379 static void
6380 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6381 {
6382         guint32 dummy;
6383         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6384                 g_error ("WriteFile returned %d\n", GetLastError ());
6385 }
6386
6387 /*
6388  * mono_image_create_pefile:
6389  * @mb: a module builder object
6390  * 
6391  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6392  * assembly->pefile where it can be easily retrieved later in chunks.
6393  */
6394 gboolean
6395 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6396 {
6397         MonoMSDOSHeader *msdos;
6398         MonoDotNetHeader *header;
6399         MonoSectionTable *section;
6400         MonoCLIHeader *cli_header;
6401         guint32 size, image_size, virtual_base, text_offset;
6402         guint32 header_start, section_start, file_offset, virtual_offset;
6403         MonoDynamicImage *assembly;
6404         MonoReflectionAssemblyBuilder *assemblyb;
6405         MonoDynamicStream pefile_stream = {0};
6406         MonoDynamicStream *pefile = &pefile_stream;
6407         int i, nsections;
6408         guint32 *rva, value;
6409         guchar *p;
6410         static const unsigned char msheader[] = {
6411                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6412                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6413                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6414                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6415                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6416                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6417                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6418                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6419         };
6420
6421         mono_error_init (error);
6422
6423         assemblyb = mb->assemblyb;
6424
6425         mono_image_basic_init (assemblyb);
6426         assembly = mb->dynamic_image;
6427
6428         assembly->pe_kind = assemblyb->pe_kind;
6429         assembly->machine = assemblyb->machine;
6430         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6431         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6432         
6433         if (!mono_image_build_metadata (mb, error))
6434                 return FALSE;
6435         
6436
6437         if (mb->is_main && assemblyb->resources) {
6438                 int len = mono_array_length (assemblyb->resources);
6439                 for (i = 0; i < len; ++i) {
6440                         if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
6441                                 return FALSE;
6442                 }
6443         }
6444
6445         if (mb->resources) {
6446                 int len = mono_array_length (mb->resources);
6447                 for (i = 0; i < len; ++i) {
6448                         if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
6449                                 return FALSE;
6450                 }
6451         }
6452
6453         if (!build_compressed_metadata (assembly, error))
6454                 return FALSE;
6455
6456         if (mb->is_main)
6457                 assembly_add_win32_resources (assembly, assemblyb);
6458
6459         nsections = calc_section_size (assembly);
6460         
6461         /* The DOS header and stub */
6462         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6463         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6464
6465         /* the dotnet header */
6466         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6467
6468         /* the section tables */
6469         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6470
6471         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6472         virtual_offset = VIRT_ALIGN;
6473         image_size = 0;
6474
6475         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6476                 if (!assembly->sections [i].size)
6477                         continue;
6478                 /* align offsets */
6479                 file_offset += FILE_ALIGN - 1;
6480                 file_offset &= ~(FILE_ALIGN - 1);
6481                 virtual_offset += VIRT_ALIGN - 1;
6482                 virtual_offset &= ~(VIRT_ALIGN - 1);
6483
6484                 assembly->sections [i].offset = file_offset;
6485                 assembly->sections [i].rva = virtual_offset;
6486
6487                 file_offset += assembly->sections [i].size;
6488                 virtual_offset += assembly->sections [i].size;
6489                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6490         }
6491
6492         file_offset += FILE_ALIGN - 1;
6493         file_offset &= ~(FILE_ALIGN - 1);
6494
6495         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6496
6497         /* back-patch info */
6498         msdos = (MonoMSDOSHeader*)pefile->data;
6499         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6500
6501         header = (MonoDotNetHeader*)(pefile->data + header_start);
6502         header->pesig [0] = 'P';
6503         header->pesig [1] = 'E';
6504         
6505         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6506         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6507         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6508         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6509         if (assemblyb->pekind == 1) {
6510                 /* it's a dll */
6511                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6512         } else {
6513                 /* it's an exe */
6514                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6515         }
6516
6517         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6518
6519         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6520         header->pe.pe_major = 6;
6521         header->pe.pe_minor = 0;
6522         size = assembly->sections [MONO_SECTION_TEXT].size;
6523         size += FILE_ALIGN - 1;
6524         size &= ~(FILE_ALIGN - 1);
6525         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6526         size = assembly->sections [MONO_SECTION_RSRC].size;
6527         size += FILE_ALIGN - 1;
6528         size &= ~(FILE_ALIGN - 1);
6529         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6530         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6531         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6532         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6533         /* pe_rva_entry_point always at the beginning of the text section */
6534         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6535
6536         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6537         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6538         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6539         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6540         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6541         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6542         size = section_start;
6543         size += FILE_ALIGN - 1;
6544         size &= ~(FILE_ALIGN - 1);
6545         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6546         size = image_size;
6547         size += VIRT_ALIGN - 1;
6548         size &= ~(VIRT_ALIGN - 1);
6549         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6550
6551         /*
6552         // Translate the PEFileKind value to the value expected by the Windows loader
6553         */
6554         {
6555                 short kind;
6556
6557                 /*
6558                 // PEFileKinds.Dll == 1
6559                 // PEFileKinds.ConsoleApplication == 2
6560                 // PEFileKinds.WindowApplication == 3
6561                 //
6562                 // need to get:
6563                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6564                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6565                 */
6566                 if (assemblyb->pekind == 3)
6567                         kind = 2;
6568                 else
6569                         kind = 3;
6570                 
6571                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6572         }    
6573         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6574         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6575         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6576         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6577         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6578         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6579
6580         /* fill data directory entries */
6581
6582         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6583         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6584
6585         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6586         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6587
6588         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6589         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6590         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6591         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6592         /* patch entrypoint name */
6593         if (assemblyb->pekind == 1)
6594                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6595         else
6596                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6597         /* patch imported function RVA name */
6598         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6599         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6600
6601         /* the import table */
6602         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6603         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6604         /* patch imported dll RVA name and other entries in the dir */
6605         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6606         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6607         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6608         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6609         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6610         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6611
6612         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6613         value = (assembly->text_rva + assembly->imp_names_offset);
6614         *p++ = (value) & 0xff;
6615         *p++ = (value >> 8) & (0xff);
6616         *p++ = (value >> 16) & (0xff);
6617         *p++ = (value >> 24) & (0xff);
6618
6619         /* the CLI header info */
6620         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6621         cli_header->ch_size = GUINT32_FROM_LE (72);
6622         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6623         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6624         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6625         if (assemblyb->entry_point) {
6626                 guint32 table_idx = 0;
6627                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6628                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6629                         table_idx = methodb->table_idx;
6630                 } else {
6631                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6632                 }
6633                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6634         } else {
6635                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6636         }
6637         /* The embedded managed resources */
6638         text_offset = assembly->text_rva + assembly->code.index;
6639         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6640         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6641         text_offset += assembly->resources.index;
6642         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6643         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6644         text_offset += assembly->meta_size;
6645         if (assembly->strong_name_size) {
6646                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6647                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6648                 text_offset += assembly->strong_name_size;
6649         }
6650
6651         /* write the section tables and section content */
6652         section = (MonoSectionTable*)(pefile->data + section_start);
6653         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6654                 static const char section_names [][7] = {
6655                         ".text", ".rsrc", ".reloc"
6656                 };
6657                 if (!assembly->sections [i].size)
6658                         continue;
6659                 strcpy (section->st_name, section_names [i]);
6660                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6661                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6662                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6663                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6664                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6665                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6666                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6667                 section ++;
6668         }
6669         
6670         checked_write_file (file, pefile->data, pefile->index);
6671         
6672         mono_dynamic_stream_reset (pefile);
6673         
6674         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6675                 if (!assembly->sections [i].size)
6676                         continue;
6677                 
6678                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6679                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6680                 
6681                 switch (i) {
6682                 case MONO_SECTION_TEXT:
6683                         /* patch entry point */
6684                         p = (guchar*)(assembly->code.data + 2);
6685                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6686                         *p++ = (value) & 0xff;
6687                         *p++ = (value >> 8) & 0xff;
6688                         *p++ = (value >> 16) & 0xff;
6689                         *p++ = (value >> 24) & 0xff;
6690                 
6691                         checked_write_file (file, assembly->code.data, assembly->code.index);
6692                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6693                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6694                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6695                                 
6696
6697                         g_free (assembly->image.raw_metadata);
6698                         break;
6699                 case MONO_SECTION_RELOC: {
6700                         struct {
6701                                 guint32 page_rva;
6702                                 guint32 block_size;
6703                                 guint16 type_and_offset;
6704                                 guint16 term;
6705                         } reloc;
6706                         
6707                         g_assert (sizeof (reloc) == 12);
6708                         
6709                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6710                         reloc.block_size = GUINT32_FROM_LE (12);
6711                         
6712                         /* 
6713                          * the entrypoint is always at the start of the text section 
6714                          * 3 is IMAGE_REL_BASED_HIGHLOW
6715                          * 2 is patch_size_rva - text_rva
6716                          */
6717                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6718                         reloc.term = 0;
6719                         
6720                         checked_write_file (file, &reloc, sizeof (reloc));
6721                         
6722                         break;
6723                 }
6724                 case MONO_SECTION_RSRC:
6725                         if (assembly->win32_res) {
6726
6727                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6728                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6729                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6730                         }
6731                         break;
6732                 default:
6733                         g_assert_not_reached ();
6734                 }
6735         }
6736         
6737         /* check that the file is properly padded */
6738         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6739                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6740         if (! SetEndOfFile (file))
6741                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6742         
6743         mono_dynamic_stream_reset (&assembly->code);
6744         mono_dynamic_stream_reset (&assembly->us);
6745         mono_dynamic_stream_reset (&assembly->blob);
6746         mono_dynamic_stream_reset (&assembly->guid);
6747         mono_dynamic_stream_reset (&assembly->sheap);
6748
6749         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6750         g_hash_table_destroy (assembly->blob_cache);
6751         assembly->blob_cache = NULL;
6752
6753         return TRUE;
6754 }
6755
6756 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6757
6758 gboolean
6759 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6760 {
6761         g_assert_not_reached ();
6762 }
6763
6764 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6765
6766 #ifndef DISABLE_REFLECTION_EMIT
6767
6768 MonoReflectionModule *
6769 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6770 {
6771         char *name;
6772         MonoImage *image;
6773         MonoImageOpenStatus status;
6774         MonoDynamicAssembly *assembly;
6775         guint32 module_count;
6776         MonoImage **new_modules;
6777         gboolean *new_modules_loaded;
6778         
6779         mono_error_init (error);
6780         
6781         name = mono_string_to_utf8_checked (fileName, error);
6782         return_val_if_nok (error, NULL);
6783
6784         image = mono_image_open (name, &status);
6785         if (!image) {
6786                 if (status == MONO_IMAGE_ERROR_ERRNO)
6787                         mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6788                 else
6789                         mono_error_set_bad_image_name (error, name, NULL);
6790                 g_free (name);
6791                 return NULL;
6792         }
6793
6794         g_free (name);
6795
6796         assembly = ab->dynamic_assembly;
6797         image->assembly = (MonoAssembly*)assembly;
6798
6799         module_count = image->assembly->image->module_count;
6800         new_modules = g_new0 (MonoImage *, module_count + 1);
6801         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6802
6803         if (image->assembly->image->modules)
6804                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6805         if (image->assembly->image->modules_loaded)
6806                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6807         new_modules [module_count] = image;
6808         new_modules_loaded [module_count] = TRUE;
6809         mono_image_addref (image);
6810
6811         g_free (image->assembly->image->modules);
6812         image->assembly->image->modules = new_modules;
6813         image->assembly->image->modules_loaded = new_modules_loaded;
6814         image->assembly->image->module_count ++;
6815
6816         mono_assembly_load_references (image, &status);
6817         if (status) {
6818                 mono_image_close (image);
6819                 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6820                 return NULL;
6821         }
6822
6823         return mono_module_get_object_checked (mono_domain_get (), image, error);
6824 }
6825
6826 #endif /* DISABLE_REFLECTION_EMIT */
6827
6828 /*
6829  * We need to return always the same object for MethodInfo, FieldInfo etc..
6830  * but we need to consider the reflected type.
6831  * type uses a different hash, since it uses custom hash/equal functions.
6832  */
6833
6834 typedef struct {
6835         gpointer item;
6836         MonoClass *refclass;
6837 } ReflectedEntry;
6838
6839 static gboolean
6840 reflected_equal (gconstpointer a, gconstpointer b) {
6841         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6842         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6843
6844         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6845 }
6846
6847 static guint
6848 reflected_hash (gconstpointer a) {
6849         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6850         return mono_aligned_addr_hash (ea->item);
6851 }
6852
6853 #define CHECK_OBJECT(t,p,k)     \
6854         do {    \
6855                 t _obj; \
6856                 ReflectedEntry e;       \
6857                 e.item = (p);   \
6858                 e.refclass = (k);       \
6859                 mono_domain_lock (domain);      \
6860                 if (!domain->refobject_hash)    \
6861                         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");  \
6862                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6863                         mono_domain_unlock (domain);    \
6864                         return _obj;    \
6865                 }       \
6866         mono_domain_unlock (domain); \
6867         } while (0)
6868
6869 #ifdef HAVE_BOEHM_GC
6870 /* ReflectedEntry doesn't need to be GC tracked */
6871 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6872 #define FREE_REFENTRY(entry) g_free ((entry))
6873 #define REFENTRY_REQUIRES_CLEANUP
6874 #else
6875 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6876 /* FIXME: */
6877 #define FREE_REFENTRY(entry)
6878 #endif
6879
6880 #define CACHE_OBJECT(t,p,o,k)   \
6881         do {    \
6882                 t _obj; \
6883         ReflectedEntry pe; \
6884         pe.item = (p); \
6885         pe.refclass = (k); \
6886         mono_domain_lock (domain); \
6887                 if (!domain->refobject_hash)    \
6888                         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");  \
6889         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6890         if (!_obj) { \
6891                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6892                     e->item = (p);      \
6893                     e->refclass = (k);  \
6894                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6895             _obj = o; \
6896         } \
6897                 mono_domain_unlock (domain);    \
6898         return _obj; \
6899         } while (0)
6900
6901 static void
6902 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6903 {
6904         mono_domain_lock (domain);
6905         if (domain->refobject_hash) {
6906         ReflectedEntry pe;
6907                 gpointer orig_pe, orig_value;
6908
6909                 pe.item = o;
6910                 pe.refclass = klass;
6911                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6912                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6913                         FREE_REFENTRY (orig_pe);
6914                 }
6915         }
6916         mono_domain_unlock (domain);
6917 }
6918
6919 #ifdef REFENTRY_REQUIRES_CLEANUP
6920 static void
6921 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6922 {
6923         FREE_REFENTRY (key);
6924 }
6925 #endif
6926
6927 void
6928 mono_reflection_cleanup_domain (MonoDomain *domain)
6929 {
6930         if (domain->refobject_hash) {
6931 /*let's avoid scanning the whole hashtable if not needed*/
6932 #ifdef REFENTRY_REQUIRES_CLEANUP
6933                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6934 #endif
6935                 mono_g_hash_table_destroy (domain->refobject_hash);
6936                 domain->refobject_hash = NULL;
6937         }
6938 }
6939
6940 #ifndef DISABLE_REFLECTION_EMIT
6941 static gpointer
6942 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6943 {
6944         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6945 }
6946
6947 static gpointer
6948 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6949 {
6950         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6951 }
6952
6953 static gboolean
6954 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
6955 {
6956         MonoDynamicImage *image = moduleb->dynamic_image;
6957         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6958         mono_error_init (error);
6959         if (!image) {
6960                 int module_count;
6961                 MonoImage **new_modules;
6962                 MonoImage *ass;
6963                 char *name, *fqname;
6964                 /*
6965                  * FIXME: we already created an image in mono_image_basic_init (), but
6966                  * we don't know which module it belongs to, since that is only 
6967                  * determined at assembly save time.
6968                  */
6969                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6970                 name = mono_string_to_utf8_checked (ab->name, error);
6971                 return_val_if_nok (error, FALSE);
6972                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
6973                 if (!is_ok (error)) {
6974                         g_free (name);
6975                         return FALSE;
6976                 }
6977                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6978
6979                 moduleb->module.image = &image->image;
6980                 moduleb->dynamic_image = image;
6981                 register_module (mono_object_domain (moduleb), moduleb, image);
6982
6983                 /* register the module with the assembly */
6984                 ass = ab->dynamic_assembly->assembly.image;
6985                 module_count = ass->module_count;
6986                 new_modules = g_new0 (MonoImage *, module_count + 1);
6987
6988                 if (ass->modules)
6989                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6990                 new_modules [module_count] = &image->image;
6991                 mono_image_addref (&image->image);
6992
6993                 g_free (ass->modules);
6994                 ass->modules = new_modules;
6995                 ass->module_count ++;
6996         }
6997         return TRUE;
6998 }
6999
7000 void
7001 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
7002 {
7003         MonoError error;
7004         (void) image_module_basic_init (moduleb, &error);
7005         mono_error_set_pending_exception (&error);
7006 }
7007
7008 void
7009 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
7010 {
7011         MonoDynamicImage *image = moduleb->dynamic_image;
7012
7013         g_assert (type->type);
7014         image->wrappers_type = mono_class_from_mono_type (type->type);
7015 }
7016
7017 #endif
7018
7019 /*
7020  * mono_assembly_get_object:
7021  * @domain: an app domain
7022  * @assembly: an assembly
7023  *
7024  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
7025  */
7026 MonoReflectionAssembly*
7027 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
7028 {
7029         MonoError error;
7030         MonoReflectionAssembly *result;
7031         result = mono_assembly_get_object_checked (domain, assembly, &error);
7032         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7033         return result;
7034 }
7035 /*
7036  * mono_assembly_get_object_checked:
7037  * @domain: an app domain
7038  * @assembly: an assembly
7039  *
7040  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
7041  */
7042 MonoReflectionAssembly*
7043 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
7044 {
7045         MonoReflectionAssembly *res;
7046         
7047         mono_error_init (error);
7048
7049         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
7050         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
7051         if (!res)
7052                 return NULL;
7053         res->assembly = assembly;
7054
7055         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
7056 }
7057
7058
7059
7060 MonoReflectionModule*   
7061 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
7062 {
7063         MonoError error;
7064         MonoReflectionModule *result;
7065         result = mono_module_get_object_checked (domain, image, &error);
7066         mono_error_cleanup (&error);
7067         return result;
7068 }
7069
7070 MonoReflectionModule*
7071 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
7072 {
7073         MonoReflectionModule *res;
7074         char* basename;
7075         
7076         mono_error_init (error);
7077         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
7078         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7079         if (!res)
7080                 return NULL;
7081
7082         res->image = image;
7083         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7084         if (!assm_obj)
7085                 return NULL;
7086         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7087
7088         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
7089         basename = g_path_get_basename (image->name);
7090         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
7091         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
7092         
7093         g_free (basename);
7094
7095         if (image->assembly->image == image) {
7096                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
7097         } else {
7098                 int i;
7099                 res->token = 0;
7100                 if (image->assembly->image->modules) {
7101                         for (i = 0; i < image->assembly->image->module_count; i++) {
7102                                 if (image->assembly->image->modules [i] == image)
7103                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
7104                         }
7105                         g_assert (res->token);
7106                 }
7107         }
7108
7109         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7110 }
7111
7112 MonoReflectionModule*
7113 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7114 {
7115         MonoError error;
7116         MonoReflectionModule *result;
7117         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7118         mono_error_cleanup (&error);
7119         return result;
7120 }
7121
7122 MonoReflectionModule*
7123 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7124 {
7125         MonoReflectionModule *res;
7126         MonoTableInfo *table;
7127         guint32 cols [MONO_FILE_SIZE];
7128         const char *name;
7129         guint32 i, name_idx;
7130         const char *val;
7131         
7132         mono_error_init (error);
7133
7134         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7135         if (!res)
7136                 return NULL;
7137
7138         table = &image->tables [MONO_TABLE_FILE];
7139         g_assert (table_index < table->rows);
7140         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7141
7142         res->image = NULL;
7143         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7144         if (!assm_obj)
7145                 return NULL;
7146         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7147         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7148
7149         /* Check whenever the row has a corresponding row in the moduleref table */
7150         table = &image->tables [MONO_TABLE_MODULEREF];
7151         for (i = 0; i < table->rows; ++i) {
7152                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7153                 val = mono_metadata_string_heap (image, name_idx);
7154                 if (strcmp (val, name) == 0)
7155                         res->image = image->modules [i];
7156         }
7157
7158         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7159         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7160         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7161         res->is_resource = cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA;
7162         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7163
7164         return res;
7165 }
7166
7167 static gboolean
7168 verify_safe_for_managed_space (MonoType *type)
7169 {
7170         switch (type->type) {
7171 #ifdef DEBUG_HARDER
7172         case MONO_TYPE_ARRAY:
7173                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7174         case MONO_TYPE_PTR:
7175                 return verify_safe_for_managed_space (type->data.type);
7176         case MONO_TYPE_SZARRAY:
7177                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7178         case MONO_TYPE_GENERICINST: {
7179                 MonoGenericInst *inst = type->data.generic_class->inst;
7180                 int i;
7181                 if (!inst->is_open)
7182                         break;
7183                 for (i = 0; i < inst->type_argc; ++i)
7184                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7185                                 return FALSE;
7186                 return TRUE;
7187         }
7188 #endif
7189         case MONO_TYPE_VAR:
7190         case MONO_TYPE_MVAR:
7191                 return TRUE;
7192         default:
7193                 return TRUE;
7194         }
7195 }
7196
7197 static MonoType*
7198 mono_type_normalize (MonoType *type)
7199 {
7200         int i;
7201         MonoGenericClass *gclass;
7202         MonoGenericInst *ginst;
7203         MonoClass *gtd;
7204         MonoGenericContainer *gcontainer;
7205         MonoType **argv = NULL;
7206         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7207
7208         if (type->type != MONO_TYPE_GENERICINST)
7209                 return type;
7210
7211         gclass = type->data.generic_class;
7212         ginst = gclass->context.class_inst;
7213         if (!ginst->is_open)
7214                 return type;
7215
7216         gtd = gclass->container_class;
7217         gcontainer = gtd->generic_container;
7218         argv = g_newa (MonoType*, ginst->type_argc);
7219
7220         for (i = 0; i < ginst->type_argc; ++i) {
7221                 MonoType *t = ginst->type_argv [i], *norm;
7222                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7223                         is_denorm_gtd = FALSE;
7224                 norm = mono_type_normalize (t);
7225                 argv [i] = norm;
7226                 if (norm != t)
7227                         requires_rebind = TRUE;
7228         }
7229
7230         if (is_denorm_gtd)
7231                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7232
7233         if (requires_rebind) {
7234                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7235                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7236         }
7237
7238         return type;
7239 }
7240 /*
7241  * mono_type_get_object:
7242  * @domain: an app domain
7243  * @type: a type
7244  *
7245  * Return an System.MonoType object representing the type @type.
7246  */
7247 MonoReflectionType*
7248 mono_type_get_object (MonoDomain *domain, MonoType *type)
7249 {
7250         MonoError error;
7251         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7252         mono_error_cleanup (&error);
7253
7254         return ret;
7255 }
7256
7257 MonoReflectionType*
7258 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7259 {
7260         MonoType *norm_type;
7261         MonoReflectionType *res;
7262         MonoClass *klass;
7263
7264         mono_error_init (error);
7265
7266         klass = mono_class_from_mono_type (type);
7267
7268         /*we must avoid using @type as it might have come
7269          * from a mono_metadata_type_dup and the caller
7270          * expects that is can be freed.
7271          * Using the right type from 
7272          */
7273         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7274
7275         /* void is very common */
7276         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7277                 return (MonoReflectionType*)domain->typeof_void;
7278
7279         /*
7280          * If the vtable of the given class was already created, we can use
7281          * the MonoType from there and avoid all locking and hash table lookups.
7282          * 
7283          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7284          * that the resulting object is different.   
7285          */
7286         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7287                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7288                 if (vtable && vtable->type)
7289                         return (MonoReflectionType *)vtable->type;
7290         }
7291
7292         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7293         mono_domain_lock (domain);
7294         if (!domain->type_hash)
7295                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7296                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7297         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7298                 mono_domain_unlock (domain);
7299                 mono_loader_unlock ();
7300                 return res;
7301         }
7302
7303         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7304          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7305          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7306          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7307          * artifact of how generics are encoded and should be transparent to managed code so we
7308          * need to weed out this diference when retrieving managed System.Type objects.
7309          */
7310         norm_type = mono_type_normalize (type);
7311         if (norm_type != type) {
7312                 res = mono_type_get_object_checked (domain, norm_type, error);
7313                 if (!mono_error_ok (error))
7314                         return NULL;
7315                 mono_g_hash_table_insert (domain->type_hash, type, res);
7316                 mono_domain_unlock (domain);
7317                 mono_loader_unlock ();
7318                 return res;
7319         }
7320
7321         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7322         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7323                 g_assert (0);
7324
7325         if (!verify_safe_for_managed_space (type)) {
7326                 mono_domain_unlock (domain);
7327                 mono_loader_unlock ();
7328                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7329                 return NULL;
7330         }
7331
7332         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7333                 gboolean is_type_done = TRUE;
7334                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7335                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7336                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7337                 */
7338                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7339                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7340
7341                         if (gparam->owner && gparam->owner->is_method) {
7342                                 MonoMethod *method = gparam->owner->owner.method;
7343                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7344                                         is_type_done = FALSE;
7345                         } else if (gparam->owner && !gparam->owner->is_method) {
7346                                 MonoClass *klass = gparam->owner->owner.klass;
7347                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7348                                         is_type_done = FALSE;
7349                         }
7350                 } 
7351
7352                 /* g_assert_not_reached (); */
7353                 /* should this be considered an error condition? */
7354                 if (is_type_done && !type->byref) {
7355                         mono_domain_unlock (domain);
7356                         mono_loader_unlock ();
7357                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7358                 }
7359         }
7360         /* This is stored in vtables/JITted code so it has to be pinned */
7361         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
7362         if (!mono_error_ok (error))
7363                 return NULL;
7364
7365         res->type = type;
7366         mono_g_hash_table_insert (domain->type_hash, type, res);
7367
7368         if (type->type == MONO_TYPE_VOID)
7369                 domain->typeof_void = (MonoObject*)res;
7370
7371         mono_domain_unlock (domain);
7372         mono_loader_unlock ();
7373         return res;
7374 }
7375
7376 /*
7377  * mono_method_get_object:
7378  * @domain: an app domain
7379  * @method: a method
7380  * @refclass: the reflected type (can be NULL)
7381  *
7382  * Return an System.Reflection.MonoMethod object representing the method @method.
7383  */
7384 MonoReflectionMethod*
7385 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7386 {
7387         MonoError error;
7388         MonoReflectionMethod *ret = NULL;
7389         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7390         mono_error_cleanup (&error);
7391         return ret;
7392 }
7393
7394 /*
7395  * mono_method_get_object_checked:
7396  * @domain: an app domain
7397  * @method: a method
7398  * @refclass: the reflected type (can be NULL)
7399  * @error: set on error.
7400  *
7401  * Return an System.Reflection.MonoMethod object representing the method @method.
7402  * Returns NULL and sets @error on error.
7403  */
7404 MonoReflectionMethod*
7405 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7406 {
7407         /*
7408          * We use the same C representation for methods and constructors, but the type 
7409          * name in C# is different.
7410          */
7411         MonoReflectionType *rt;
7412         MonoClass *klass;
7413         MonoReflectionMethod *ret;
7414
7415         mono_error_init (error);
7416
7417         if (method->is_inflated) {
7418                 MonoReflectionGenericMethod *gret;
7419
7420                 if (!refclass)
7421                         refclass = method->klass;
7422                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7423                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7424                         klass = mono_class_get_mono_generic_cmethod_class ();
7425                 } else {
7426                         klass = mono_class_get_mono_generic_method_class ();
7427                 }
7428                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7429                 if (!mono_error_ok (error))
7430                         goto leave;
7431                 gret->method.method = method;
7432
7433                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7434
7435                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7436                 if (!mono_error_ok (error))
7437                     goto leave;
7438
7439                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7440
7441                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7442         }
7443
7444         if (!refclass)
7445                 refclass = method->klass;
7446
7447         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7448         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7449                 klass = mono_class_get_mono_cmethod_class ();
7450         }
7451         else {
7452                 klass = mono_class_get_mono_method_class ();
7453         }
7454         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7455         if (!mono_error_ok (error))
7456                 goto leave;
7457         ret->method = method;
7458
7459         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7460         if (!mono_error_ok (error))
7461                 goto leave;
7462
7463         MONO_OBJECT_SETREF (ret, reftype, rt);
7464
7465         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7466
7467 leave:
7468         g_assert (!mono_error_ok (error));
7469         return NULL;
7470 }
7471
7472 /*
7473  * mono_method_clear_object:
7474  *
7475  *   Clear the cached reflection objects for the dynamic method METHOD.
7476  */
7477 void
7478 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7479 {
7480         MonoClass *klass;
7481         g_assert (method_is_dynamic (method));
7482
7483         klass = method->klass;
7484         while (klass) {
7485                 clear_cached_object (domain, method, klass);
7486                 klass = klass->parent;
7487         }
7488         /* Added by mono_param_get_objects () */
7489         clear_cached_object (domain, &(method->signature), NULL);
7490         klass = method->klass;
7491         while (klass) {
7492                 clear_cached_object (domain, &(method->signature), klass);
7493                 klass = klass->parent;
7494         }
7495 }
7496
7497 /*
7498  * mono_field_get_object:
7499  * @domain: an app domain
7500  * @klass: a type
7501  * @field: a field
7502  *
7503  * Return an System.Reflection.MonoField object representing the field @field
7504  * in class @klass.
7505  */
7506 MonoReflectionField*
7507 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7508 {
7509         MonoError error;
7510         MonoReflectionField *result;
7511         result = mono_field_get_object_checked (domain, klass, field, &error);
7512         mono_error_cleanup (&error);
7513         return result;
7514 }
7515
7516 /*
7517  * mono_field_get_object_checked:
7518  * @domain: an app domain
7519  * @klass: a type
7520  * @field: a field
7521  * @error: set on error
7522  *
7523  * Return an System.Reflection.MonoField object representing the field @field
7524  * in class @klass. On error, returns NULL and sets @error.
7525  */
7526 MonoReflectionField*
7527 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7528 {
7529         MonoReflectionType *rt;
7530         MonoReflectionField *res;
7531
7532         mono_error_init (error);
7533
7534         CHECK_OBJECT (MonoReflectionField *, field, klass);
7535         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7536         if (!res)
7537                 return NULL;
7538         res->klass = klass;
7539         res->field = field;
7540         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7541
7542         if (is_field_on_inst (field)) {
7543                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7544
7545                 rt = mono_type_get_object_checked (domain, field->type, error);
7546                 if (!mono_error_ok (error))
7547                         return NULL;
7548
7549                 MONO_OBJECT_SETREF (res, type, rt);
7550         } else {
7551                 if (field->type) {
7552                         rt = mono_type_get_object_checked (domain, field->type, error);
7553                         if (!mono_error_ok (error))
7554                                 return NULL;
7555
7556                         MONO_OBJECT_SETREF (res, type, rt);
7557                 }
7558                 res->attrs = mono_field_get_flags (field);
7559         }
7560         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7561 }
7562
7563 /*
7564  * mono_property_get_object:
7565  * @domain: an app domain
7566  * @klass: a type
7567  * @property: a property
7568  *
7569  * Return an System.Reflection.MonoProperty object representing the property @property
7570  * in class @klass.
7571  */
7572 MonoReflectionProperty*
7573 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7574 {
7575         MonoError error;
7576         MonoReflectionProperty *result;
7577         result = mono_property_get_object_checked (domain, klass, property, &error);
7578         mono_error_cleanup (&error);
7579         return result;
7580 }
7581
7582 /**
7583  * mono_property_get_object:
7584  * @domain: an app domain
7585  * @klass: a type
7586  * @property: a property
7587  * @error: set on error
7588  *
7589  * Return an System.Reflection.MonoProperty object representing the property @property
7590  * in class @klass.  On error returns NULL and sets @error.
7591  */
7592 MonoReflectionProperty*
7593 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7594 {
7595         MonoReflectionProperty *res;
7596
7597         mono_error_init (error);
7598
7599         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7600         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7601         if (!res)
7602                 return NULL;
7603         res->klass = klass;
7604         res->property = property;
7605         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7606 }
7607
7608 /*
7609  * mono_event_get_object:
7610  * @domain: an app domain
7611  * @klass: a type
7612  * @event: a event
7613  *
7614  * Return an System.Reflection.MonoEvent object representing the event @event
7615  * in class @klass.
7616  */
7617 MonoReflectionEvent*
7618 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7619 {
7620         MonoError error;
7621         MonoReflectionEvent *result;
7622         result = mono_event_get_object_checked (domain, klass, event, &error);
7623         mono_error_cleanup (&error);
7624         return result;
7625 }
7626
7627 /**
7628  * mono_event_get_object_checked:
7629  * @domain: an app domain
7630  * @klass: a type
7631  * @event: a event
7632  * @error: set on error
7633  *
7634  * Return an System.Reflection.MonoEvent object representing the event @event
7635  * in class @klass. On failure sets @error and returns NULL
7636  */
7637 MonoReflectionEvent*
7638 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7639 {
7640         MonoReflectionEvent *res;
7641         MonoReflectionMonoEvent *mono_event;
7642
7643         mono_error_init (error);
7644         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7645         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7646         if (!mono_event)
7647                 return NULL;
7648         mono_event->klass = klass;
7649         mono_event->event = event;
7650         res = (MonoReflectionEvent*)mono_event;
7651         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7652 }
7653
7654 /**
7655  * mono_get_reflection_missing_object:
7656  * @domain: Domain where the object lives
7657  *
7658  * Returns the System.Reflection.Missing.Value singleton object
7659  * (of type System.Reflection.Missing).
7660  *
7661  * Used as the value for ParameterInfo.DefaultValue when Optional
7662  * is present
7663  */
7664 static MonoObject *
7665 mono_get_reflection_missing_object (MonoDomain *domain)
7666 {
7667         MonoError error;
7668         MonoObject *obj;
7669         static MonoClassField *missing_value_field = NULL;
7670         
7671         if (!missing_value_field) {
7672                 MonoClass *missing_klass;
7673                 missing_klass = mono_class_get_missing_class ();
7674                 mono_class_init (missing_klass);
7675                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7676                 g_assert (missing_value_field);
7677         }
7678         obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7679         mono_error_assert_ok (&error);
7680         return obj;
7681 }
7682
7683 static MonoObject*
7684 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7685 {
7686         if (!*dbnull)
7687                 *dbnull = mono_get_dbnull_object (domain);
7688         return *dbnull;
7689 }
7690
7691 static MonoObject*
7692 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7693 {
7694         if (!*reflection_missing)
7695                 *reflection_missing = mono_get_reflection_missing_object (domain);
7696         return *reflection_missing;
7697 }
7698
7699 /*
7700  * mono_param_get_objects:
7701  * @domain: an app domain
7702  * @method: a method
7703  *
7704  * Return an System.Reflection.ParameterInfo array object representing the parameters
7705  * in the method @method.
7706  */
7707 MonoArray*
7708 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7709 {
7710         static MonoClass *System_Reflection_ParameterInfo;
7711         static MonoClass *System_Reflection_ParameterInfo_array;
7712         MonoArray *res = NULL;
7713         MonoReflectionMethod *member = NULL;
7714         MonoReflectionParameter *param = NULL;
7715         char **names = NULL, **blobs = NULL;
7716         guint32 *types = NULL;
7717         MonoType *type = NULL;
7718         MonoObject *dbnull = NULL;
7719         MonoObject *missing = NULL;
7720         MonoMarshalSpec **mspecs = NULL;
7721         MonoMethodSignature *sig = NULL;
7722         MonoVTable *pinfo_vtable;
7723         MonoReflectionType *rt;
7724         int i;
7725
7726         mono_error_init (error);
7727         
7728         if (!System_Reflection_ParameterInfo_array) {
7729                 MonoClass *klass;
7730
7731                 klass = mono_class_get_mono_parameter_info_class ();
7732
7733                 mono_memory_barrier ();
7734                 System_Reflection_ParameterInfo = klass; 
7735
7736         
7737                 klass = mono_array_class_get (klass, 1);
7738                 mono_memory_barrier ();
7739                 System_Reflection_ParameterInfo_array = klass;
7740         }
7741
7742         sig = mono_method_signature_checked (method, error);
7743         if (!mono_error_ok (error))
7744                 goto leave;
7745
7746         if (!sig->param_count) {
7747                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7748                 if (!res)
7749                         goto leave;
7750
7751                 return res;
7752         }
7753
7754         /* Note: the cache is based on the address of the signature into the method
7755          * since we already cache MethodInfos with the method as keys.
7756          */
7757         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7758
7759         member = mono_method_get_object_checked (domain, method, refclass, error);
7760         if (!member)
7761                 goto leave;
7762         names = g_new (char *, sig->param_count);
7763         mono_method_get_param_names (method, (const char **) names);
7764
7765         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7766         mono_method_get_marshal_info (method, mspecs);
7767
7768         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7769         if (!res)
7770                 goto leave;
7771
7772         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7773         for (i = 0; i < sig->param_count; ++i) {
7774                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7775                 if (!param)
7776                         goto leave;
7777
7778                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7779                 if (!rt)
7780                         goto leave;
7781
7782                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7783
7784                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7785
7786                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7787
7788                 param->PositionImpl = i;
7789                 param->AttrsImpl = sig->params [i]->attrs;
7790
7791                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7792                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7793                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7794                         else
7795                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7796                 } else {
7797
7798                         if (!blobs) {
7799                                 blobs = g_new0 (char *, sig->param_count);
7800                                 types = g_new0 (guint32, sig->param_count);
7801                                 get_default_param_value_blobs (method, blobs, types); 
7802                         }
7803
7804                         /* Build MonoType for the type from the Constant Table */
7805                         if (!type)
7806                                 type = g_new0 (MonoType, 1);
7807                         type->type = (MonoTypeEnum)types [i];
7808                         type->data.klass = NULL;
7809                         if (types [i] == MONO_TYPE_CLASS)
7810                                 type->data.klass = mono_defaults.object_class;
7811                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7812                                 /* For enums, types [i] contains the base type */
7813
7814                                         type->type = MONO_TYPE_VALUETYPE;
7815                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7816                         } else
7817                                 type->data.klass = mono_class_from_mono_type (type);
7818
7819                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7820                         if (!is_ok (error))
7821                                 goto leave;
7822                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7823
7824                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7825                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7826                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7827                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7828                                 else
7829                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7830                         }
7831                         
7832                 }
7833
7834                 if (mspecs [i + 1]) {
7835                         MonoReflectionMarshalAsAttribute* mobj;
7836                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7837                         if (!mobj)
7838                                 goto leave;
7839                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7840                 }
7841                 
7842                 mono_array_setref (res, i, param);
7843         }
7844
7845 leave:
7846         g_free (names);
7847         g_free (blobs);
7848         g_free (types);
7849         g_free (type);
7850
7851         if (sig) {
7852                 for (i = sig->param_count; i >= 0; i--) {
7853                         if (mspecs [i])
7854                                 mono_metadata_free_marshal_spec (mspecs [i]);
7855                 }
7856         }
7857         g_free (mspecs);
7858
7859         if (!is_ok (error))
7860                 return NULL;
7861         
7862         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7863 }
7864
7865 MonoArray*
7866 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7867 {
7868         MonoError error;
7869         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7870         mono_error_assert_ok (&error);
7871         return result;
7872 }
7873
7874 /*
7875  * mono_method_body_get_object:
7876  * @domain: an app domain
7877  * @method: a method
7878  *
7879  * Return an System.Reflection.MethodBody object representing the method @method.
7880  */
7881 MonoReflectionMethodBody*
7882 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7883 {
7884         MonoError error;
7885         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7886         mono_error_cleanup (&error);
7887         return result;
7888 }
7889
7890 /**
7891  * mono_method_body_get_object_checked:
7892  * @domain: an app domain
7893  * @method: a method
7894  * @error: set on error
7895  *
7896  * Return an System.Reflection.MethodBody object representing the
7897  * method @method.  On failure, returns NULL and sets @error.
7898  */
7899 MonoReflectionMethodBody*
7900 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7901 {
7902         MonoReflectionMethodBody *ret;
7903         MonoMethodHeader *header;
7904         MonoImage *image;
7905         MonoReflectionType *rt;
7906         guint32 method_rva, local_var_sig_token;
7907         char *ptr;
7908         unsigned char format, flags;
7909         int i;
7910
7911         mono_error_init (error);
7912
7913         /* for compatibility with .net */
7914         if (method_is_dynamic (method)) {
7915                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7916                 return NULL;
7917         }
7918
7919         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7920
7921         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7922                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7923             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7924                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7925             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7926                 return NULL;
7927
7928         image = method->klass->image;
7929         header = mono_method_get_header_checked (method, error);
7930         return_val_if_nok (error, NULL);
7931
7932         if (!image_is_dynamic (image)) {
7933                 /* Obtain local vars signature token */
7934                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7935                 ptr = mono_image_rva_map (image, method_rva);
7936                 flags = *(const unsigned char *) ptr;
7937                 format = flags & METHOD_HEADER_FORMAT_MASK;
7938                 switch (format){
7939                 case METHOD_HEADER_TINY_FORMAT:
7940                         local_var_sig_token = 0;
7941                         break;
7942                 case METHOD_HEADER_FAT_FORMAT:
7943                         ptr += 2;
7944                         ptr += 2;
7945                         ptr += 4;
7946                         local_var_sig_token = read32 (ptr);
7947                         break;
7948                 default:
7949                         g_assert_not_reached ();
7950                 }
7951         } else
7952                 local_var_sig_token = 0; //FIXME
7953
7954         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7955         if (!is_ok (error))
7956                 goto fail;
7957
7958         ret->init_locals = header->init_locals;
7959         ret->max_stack = header->max_stack;
7960         ret->local_var_sig_token = local_var_sig_token;
7961         MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
7962         if (!is_ok (error))
7963                 goto fail;
7964         MONO_OBJECT_SETREF (ret, il, il_arr);
7965         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7966
7967         /* Locals */
7968         MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
7969         if (!is_ok (error))
7970                 goto fail;
7971         MONO_OBJECT_SETREF (ret, locals, locals_arr);
7972         for (i = 0; i < header->num_locals; ++i) {
7973                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7974                 if (!is_ok (error))
7975                         goto fail;
7976
7977                 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7978                 if (!is_ok (error))
7979                         goto fail;
7980
7981                 MONO_OBJECT_SETREF (info, local_type, rt);
7982
7983                 info->is_pinned = header->locals [i]->pinned;
7984                 info->local_index = i;
7985                 mono_array_setref (ret->locals, i, info);
7986         }
7987
7988         /* Exceptions */
7989         MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
7990         if (!is_ok (error))
7991                 goto fail;
7992         MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
7993         for (i = 0; i < header->num_clauses; ++i) {
7994                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7995                 if (!is_ok (error))
7996                         goto fail;
7997                 MonoExceptionClause *clause = &header->clauses [i];
7998
7999                 info->flags = clause->flags;
8000                 info->try_offset = clause->try_offset;
8001                 info->try_length = clause->try_len;
8002                 info->handler_offset = clause->handler_offset;
8003                 info->handler_length = clause->handler_len;
8004                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
8005                         info->filter_offset = clause->data.filter_offset;
8006                 else if (clause->data.catch_class) {
8007                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
8008                         if (!is_ok (error))
8009                                 goto fail;
8010
8011                         MONO_OBJECT_SETREF (info, catch_type, rt);
8012                 }
8013
8014                 mono_array_setref (ret->clauses, i, info);
8015         }
8016
8017         mono_metadata_free_mh (header);
8018         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
8019         return ret;
8020
8021 fail:
8022         mono_metadata_free_mh (header);
8023         return NULL;
8024 }
8025
8026 /**
8027  * mono_get_dbnull_object:
8028  * @domain: Domain where the object lives
8029  *
8030  * Returns the System.DBNull.Value singleton object
8031  *
8032  * Used as the value for ParameterInfo.DefaultValue 
8033  */
8034 MonoObject *
8035 mono_get_dbnull_object (MonoDomain *domain)
8036 {
8037         MonoError error;
8038         MonoObject *obj;
8039         static MonoClassField *dbnull_value_field = NULL;
8040         
8041         if (!dbnull_value_field) {
8042                 MonoClass *dbnull_klass;
8043                 dbnull_klass = mono_class_get_dbnull_class ();
8044                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
8045                 g_assert (dbnull_value_field);
8046         }
8047         obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
8048         mono_error_assert_ok (&error);
8049         return obj;
8050 }
8051
8052 static void
8053 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
8054 {
8055         guint32 param_index, i, lastp, crow = 0;
8056         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
8057         gint32 idx;
8058
8059         MonoClass *klass = method->klass;
8060         MonoImage *image = klass->image;
8061         MonoMethodSignature *methodsig = mono_method_signature (method);
8062
8063         MonoTableInfo *constt;
8064         MonoTableInfo *methodt;
8065         MonoTableInfo *paramt;
8066
8067         if (!methodsig->param_count)
8068                 return;
8069
8070         mono_class_init (klass);
8071
8072         if (image_is_dynamic (klass->image)) {
8073                 MonoReflectionMethodAux *aux;
8074                 if (method->is_inflated)
8075                         method = ((MonoMethodInflated*)method)->declaring;
8076                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8077                 if (aux && aux->param_defaults) {
8078                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
8079                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
8080                 }
8081                 return;
8082         }
8083
8084         methodt = &klass->image->tables [MONO_TABLE_METHOD];
8085         paramt = &klass->image->tables [MONO_TABLE_PARAM];
8086         constt = &image->tables [MONO_TABLE_CONSTANT];
8087
8088         idx = mono_method_get_index (method) - 1;
8089         g_assert (idx != -1);
8090
8091         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
8092         if (idx + 1 < methodt->rows)
8093                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
8094         else
8095                 lastp = paramt->rows + 1;
8096
8097         for (i = param_index; i < lastp; ++i) {
8098                 guint32 paramseq;
8099
8100                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
8101                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
8102
8103                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
8104                         continue;
8105
8106                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
8107                 if (!crow) {
8108                         continue;
8109                 }
8110         
8111                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
8112                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
8113                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8114         }
8115
8116         return;
8117 }
8118
8119 MonoObject *
8120 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8121 {
8122         void *retval;
8123         MonoClass *klass;
8124         MonoObject *object;
8125         MonoType *basetype = type;
8126
8127         mono_error_init (error);
8128
8129         if (!blob)
8130                 return NULL;
8131         
8132         klass = mono_class_from_mono_type (type);
8133         if (klass->valuetype) {
8134                 object = mono_object_new_checked (domain, klass, error);
8135                 return_val_if_nok (error, NULL);
8136                 retval = ((gchar *) object + sizeof (MonoObject));
8137                 if (klass->enumtype)
8138                         basetype = mono_class_enum_basetype (klass);
8139         } else {
8140                 retval = &object;
8141         }
8142                         
8143         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval, error))
8144                 return object;
8145         else
8146                 return NULL;
8147 }
8148
8149 static int
8150 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8151         int found_sep;
8152         char *s;
8153         gboolean quoted = FALSE;
8154
8155         memset (assembly, 0, sizeof (MonoAssemblyName));
8156         assembly->culture = "";
8157         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8158
8159         if (*p == '"') {
8160                 quoted = TRUE;
8161                 p++;
8162         }
8163         assembly->name = p;
8164         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8165                 p++;
8166         if (quoted) {
8167                 if (*p != '"')
8168                         return 1;
8169                 *p = 0;
8170                 p++;
8171         }
8172         if (*p != ',')
8173                 return 1;
8174         *p = 0;
8175         /* Remove trailing whitespace */
8176         s = p - 1;
8177         while (*s && g_ascii_isspace (*s))
8178                 *s-- = 0;
8179         p ++;
8180         while (g_ascii_isspace (*p))
8181                 p++;
8182         while (*p) {
8183                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8184                         p += 8;
8185                         assembly->major = strtoul (p, &s, 10);
8186                         if (s == p || *s != '.')
8187                                 return 1;
8188                         p = ++s;
8189                         assembly->minor = strtoul (p, &s, 10);
8190                         if (s == p || *s != '.')
8191                                 return 1;
8192                         p = ++s;
8193                         assembly->build = strtoul (p, &s, 10);
8194                         if (s == p || *s != '.')
8195                                 return 1;
8196                         p = ++s;
8197                         assembly->revision = strtoul (p, &s, 10);
8198                         if (s == p)
8199                                 return 1;
8200                         p = s;
8201                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8202                         p += 8;
8203                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8204                                 assembly->culture = "";
8205                                 p += 7;
8206                         } else {
8207                                 assembly->culture = p;
8208                                 while (*p && *p != ',') {
8209                                         p++;
8210                                 }
8211                         }
8212                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8213                         p += 15;
8214                         if (strncmp (p, "null", 4) == 0) {
8215                                 p += 4;
8216                         } else {
8217                                 int len;
8218                                 gchar *start = p;
8219                                 while (*p && *p != ',') {
8220                                         p++;
8221                                 }
8222                                 len = (p - start + 1);
8223                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8224                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8225                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8226                         }
8227                 } else {
8228                         while (*p && *p != ',')
8229                                 p++;
8230                 }
8231                 found_sep = 0;
8232                 while (g_ascii_isspace (*p) || *p == ',') {
8233                         *p++ = 0;
8234                         found_sep = 1;
8235                         continue;
8236                 }
8237                 /* failed */
8238                 if (!found_sep)
8239                         return 1;
8240         }
8241
8242         return 0;
8243 }
8244
8245 /*
8246  * mono_reflection_parse_type:
8247  * @name: type name
8248  *
8249  * Parse a type name as accepted by the GetType () method and output the info
8250  * extracted in the info structure.
8251  * the name param will be mangled, so, make a copy before passing it to this function.
8252  * The fields in info will be valid until the memory pointed to by name is valid.
8253  *
8254  * See also mono_type_get_name () below.
8255  *
8256  * Returns: 0 on parse error.
8257  */
8258 static int
8259 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8260                              MonoTypeNameParse *info)
8261 {
8262         char *start, *p, *w, *last_point, *startn;
8263         int in_modifiers = 0;
8264         int isbyref = 0, rank = 0, isptr = 0;
8265
8266         start = p = w = name;
8267
8268         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8269         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8270         info->name = info->name_space = NULL;
8271         info->nested = NULL;
8272         info->modifiers = NULL;
8273         info->type_arguments = NULL;
8274
8275         /* last_point separates the namespace from the name */
8276         last_point = NULL;
8277         /* Skips spaces */
8278         while (*p == ' ') p++, start++, w++, name++;
8279
8280         while (*p) {
8281                 switch (*p) {
8282                 case '+':
8283                         *p = 0; /* NULL terminate the name */
8284                         startn = p + 1;
8285                         info->nested = g_list_append (info->nested, startn);
8286                         /* we have parsed the nesting namespace + name */
8287                         if (info->name)
8288                                 break;
8289                         if (last_point) {
8290                                 info->name_space = start;
8291                                 *last_point = 0;
8292                                 info->name = last_point + 1;
8293                         } else {
8294                                 info->name_space = (char *)"";
8295                                 info->name = start;
8296                         }
8297                         break;
8298                 case '.':
8299                         last_point = p;
8300                         break;
8301                 case '\\':
8302                         ++p;
8303                         break;
8304                 case '&':
8305                 case '*':
8306                 case '[':
8307                 case ',':
8308                 case ']':
8309                         in_modifiers = 1;
8310                         break;
8311                 default:
8312                         break;
8313                 }
8314                 if (in_modifiers)
8315                         break;
8316                 // *w++ = *p++;
8317                 p++;
8318         }
8319         
8320         if (!info->name) {
8321                 if (last_point) {
8322                         info->name_space = start;
8323                         *last_point = 0;
8324                         info->name = last_point + 1;
8325                 } else {
8326                         info->name_space = (char *)"";
8327                         info->name = start;
8328                 }
8329         }
8330         while (*p) {
8331                 switch (*p) {
8332                 case '&':
8333                         if (isbyref) /* only one level allowed by the spec */
8334                                 return 0;
8335                         isbyref = 1;
8336                         isptr = 0;
8337                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8338                         *p++ = 0;
8339                         break;
8340                 case '*':
8341                         if (isbyref) /* pointer to ref not okay */
8342                                 return 0;
8343                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8344                         isptr = 1;
8345                         *p++ = 0;
8346                         break;
8347                 case '[':
8348                         if (isbyref) /* array of ref and generic ref are not okay */
8349                                 return 0;
8350                         //Decide if it's an array of a generic argument list
8351                         *p++ = 0;
8352
8353                         if (!*p) //XXX test
8354                                 return 0;
8355                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8356                                 isptr = 0;
8357                                 rank = 1;
8358                                 while (*p) {
8359                                         if (*p == ']')
8360                                                 break;
8361                                         if (*p == ',')
8362                                                 rank++;
8363                                         else if (*p == '*') /* '*' means unknown lower bound */
8364                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8365                                         else
8366                                                 return 0;
8367                                         ++p;
8368                                 }
8369                                 if (*p++ != ']')
8370                                         return 0;
8371                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8372                         } else {
8373                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8374                                         return 0;
8375                                 isptr = 0;
8376                                 info->type_arguments = g_ptr_array_new ();
8377                                 while (*p) {
8378                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8379                                         gboolean fqname = FALSE;
8380
8381                                         g_ptr_array_add (info->type_arguments, subinfo);
8382
8383                                         while (*p == ' ') p++;
8384                                         if (*p == '[') {
8385                                                 p++;
8386                                                 fqname = TRUE;
8387                                         }
8388
8389                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8390                                                 return 0;
8391
8392                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8393                                         if (fqname && (*p != ']')) {
8394                                                 char *aname;
8395
8396                                                 if (*p != ',')
8397                                                         return 0;
8398                                                 *p++ = 0;
8399
8400                                                 aname = p;
8401                                                 while (*p && (*p != ']'))
8402                                                         p++;
8403
8404                                                 if (*p != ']')
8405                                                         return 0;
8406
8407                                                 *p++ = 0;
8408                                                 while (*aname) {
8409                                                         if (g_ascii_isspace (*aname)) {
8410                                                                 ++aname;
8411                                                                 continue;
8412                                                         }
8413                                                         break;
8414                                                 }
8415                                                 if (!*aname ||
8416                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8417                                                         return 0;
8418                                         } else if (fqname && (*p == ']')) {
8419                                                 *p++ = 0;
8420                                         }
8421                                         if (*p == ']') {
8422                                                 *p++ = 0;
8423                                                 break;
8424                                         } else if (!*p) {
8425                                                 return 0;
8426                                         }
8427                                         *p++ = 0;
8428                                 }
8429                         }
8430                         break;
8431                 case ']':
8432                         if (is_recursed)
8433                                 goto end;
8434                         return 0;
8435                 case ',':
8436                         if (is_recursed)
8437                                 goto end;
8438                         *p++ = 0;
8439                         while (*p) {
8440                                 if (g_ascii_isspace (*p)) {
8441                                         ++p;
8442                                         continue;
8443                                 }
8444                                 break;
8445                         }
8446                         if (!*p)
8447                                 return 0; /* missing assembly name */
8448                         if (!assembly_name_to_aname (&info->assembly, p))
8449                                 return 0;
8450                         break;
8451                 default:
8452                         return 0;
8453                 }
8454                 if (info->assembly.name)
8455                         break;
8456         }
8457         // *w = 0; /* terminate class name */
8458  end:
8459         if (!info->name || !*info->name)
8460                 return 0;
8461         if (endptr)
8462                 *endptr = p;
8463         /* add other consistency checks */
8464         return 1;
8465 }
8466
8467
8468 /**
8469  * mono_identifier_unescape_type_name_chars:
8470  * @identifier: the display name of a mono type
8471  *
8472  * Returns:
8473  *  The name in internal form, that is without escaping backslashes.
8474  *
8475  *  The string is modified in place!
8476  */
8477 char*
8478 mono_identifier_unescape_type_name_chars(char* identifier)
8479 {
8480         char *w, *r;
8481         if (!identifier)
8482                 return NULL;
8483         for (w = r = identifier; *r != 0; r++)
8484         {
8485                 char c = *r;
8486                 if (c == '\\') {
8487                         r++;
8488                         if (*r == 0)
8489                                 break;
8490                         c = *r;
8491                 }
8492                 *w = c;
8493                 w++;
8494         }
8495         if (w != r)
8496                 *w = 0;
8497         return identifier;
8498 }
8499
8500 void
8501 mono_identifier_unescape_info (MonoTypeNameParse* info);
8502
8503 static void
8504 unescape_each_type_argument(void* data, void* user_data)
8505 {
8506         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8507         mono_identifier_unescape_info (info);
8508 }
8509
8510 static void
8511 unescape_each_nested_name (void* data, void* user_data)
8512 {
8513         char* nested_name = (char*) data;
8514         mono_identifier_unescape_type_name_chars(nested_name);
8515 }
8516
8517 /**
8518  * mono_identifier_unescape_info:
8519  *
8520  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8521  *
8522  * Returns: nothing.
8523  *
8524  * Destructively updates the info by unescaping the identifiers that
8525  * comprise the type namespace, name, nested types (if any) and
8526  * generic type arguments (if any).
8527  *
8528  * The resulting info has the names in internal form.
8529  *
8530  */
8531 void
8532 mono_identifier_unescape_info (MonoTypeNameParse *info)
8533 {
8534         if (!info)
8535                 return;
8536         mono_identifier_unescape_type_name_chars(info->name_space);
8537         mono_identifier_unescape_type_name_chars(info->name);
8538         // but don't escape info->assembly
8539         if (info->type_arguments)
8540                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8541         if (info->nested)
8542                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8543 }
8544
8545 int
8546 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8547 {
8548         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8549         if (ok) {
8550                 mono_identifier_unescape_info (info);
8551         }
8552         return ok;
8553 }
8554
8555 static MonoType*
8556 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8557 {
8558         gboolean type_resolve = FALSE;
8559         MonoType *type;
8560         MonoImage *rootimage = image;
8561
8562         mono_error_init (error);
8563
8564         if (info->assembly.name) {
8565                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8566                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8567                         /* 
8568                          * This could happen in the AOT compiler case when the search hook is not
8569                          * installed.
8570                          */
8571                         assembly = image->assembly;
8572                 if (!assembly) {
8573                         /* then we must load the assembly ourselve - see #60439 */
8574                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8575                         if (!assembly)
8576                                 return NULL;
8577                 }
8578                 image = assembly->image;
8579         } else if (!image) {
8580                 image = mono_defaults.corlib;
8581         }
8582
8583         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8584         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8585                 /* ignore the error and try again */
8586                 mono_error_cleanup (error);
8587                 mono_error_init (error);
8588                 image = mono_defaults.corlib;
8589                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8590         }
8591
8592         return type;
8593 }
8594
8595 /**
8596  * mono_reflection_get_type_internal:
8597  *
8598  * Returns: may return NULL on success, sets error on failure.
8599  */
8600 static MonoType*
8601 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8602 {
8603         MonoClass *klass;
8604         GList *mod;
8605         int modval;
8606         gboolean bounded = FALSE;
8607         
8608         mono_error_init (error);
8609         if (!image)
8610                 image = mono_defaults.corlib;
8611
8612         if (!rootimage)
8613                 rootimage = mono_defaults.corlib;
8614
8615         if (ignorecase)
8616                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8617         else
8618                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8619
8620         if (!klass)
8621                 return NULL;
8622
8623         for (mod = info->nested; mod; mod = mod->next) {
8624                 gpointer iter = NULL;
8625                 MonoClass *parent;
8626
8627                 parent = klass;
8628                 mono_class_init (parent);
8629
8630                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8631                         char *lastp;
8632                         char *nested_name, *nested_nspace;
8633                         gboolean match = TRUE;
8634
8635                         lastp = strrchr ((const char *)mod->data, '.');
8636                         if (lastp) {
8637                                 /* Nested classes can have namespaces */
8638                                 int nspace_len;
8639
8640                                 nested_name = g_strdup (lastp + 1);
8641                                 nspace_len = lastp - (char*)mod->data;
8642                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8643                                 memcpy (nested_nspace, mod->data, nspace_len);
8644                                 nested_nspace [nspace_len] = '\0';
8645
8646                         } else {
8647                                 nested_name = (char *)mod->data;
8648                                 nested_nspace = NULL;
8649                         }
8650
8651                         if (nested_nspace) {
8652                                 if (ignorecase) {
8653                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8654                                                 match = FALSE;
8655                                 } else {
8656                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8657                                                 match = FALSE;
8658                                 }
8659                         }
8660                         if (match) {
8661                                 if (ignorecase) {
8662                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8663                                                 match = FALSE;
8664                                 } else {
8665                                         if (strcmp (klass->name, nested_name) != 0)
8666                                                 match = FALSE;
8667                                 }
8668                         }
8669                         if (lastp) {
8670                                 g_free (nested_name);
8671                                 g_free (nested_nspace);
8672                         }
8673                         if (match)
8674                                 break;
8675                 }
8676
8677                 if (!klass)
8678                         break;
8679         }
8680         if (!klass)
8681                 return NULL;
8682
8683         if (info->type_arguments) {
8684                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8685                 MonoReflectionType *the_type;
8686                 MonoType *instance;
8687                 int i;
8688
8689                 for (i = 0; i < info->type_arguments->len; i++) {
8690                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8691
8692                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8693                         if (!type_args [i]) {
8694                                 g_free (type_args);
8695                                 return NULL;
8696                         }
8697                 }
8698
8699                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8700                 if (!the_type)
8701                         return NULL;
8702
8703                 instance = mono_reflection_bind_generic_parameters (
8704                         the_type, info->type_arguments->len, type_args, error);
8705
8706                 g_free (type_args);
8707                 if (!instance)
8708                         return NULL;
8709
8710                 klass = mono_class_from_mono_type (instance);
8711         }
8712
8713         for (mod = info->modifiers; mod; mod = mod->next) {
8714                 modval = GPOINTER_TO_UINT (mod->data);
8715                 if (!modval) { /* byref: must be last modifier */
8716                         return &klass->this_arg;
8717                 } else if (modval == -1) {
8718                         klass = mono_ptr_class_get (&klass->byval_arg);
8719                 } else if (modval == -2) {
8720                         bounded = TRUE;
8721                 } else { /* array rank */
8722                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8723                 }
8724         }
8725
8726         return &klass->byval_arg;
8727 }
8728
8729 /*
8730  * mono_reflection_get_type:
8731  * @image: a metadata context
8732  * @info: type description structure
8733  * @ignorecase: flag for case-insensitive string compares
8734  * @type_resolve: whenever type resolve was already tried
8735  *
8736  * Build a MonoType from the type description in @info.
8737  * 
8738  */
8739
8740 MonoType*
8741 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8742         MonoError error;
8743         MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8744         mono_error_cleanup (&error);
8745         return result;
8746 }
8747
8748 /**
8749  * mono_reflection_get_type_checked:
8750  * @rootimage: the image of the currently active managed caller
8751  * @image: a metadata context
8752  * @info: type description structure
8753  * @ignorecase: flag for case-insensitive string compares
8754  * @type_resolve: whenever type resolve was already tried
8755  * @error: set on error.
8756  *
8757  * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8758  *
8759  */
8760 MonoType*
8761 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8762         mono_error_init (error);
8763         return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
8764 }
8765
8766
8767 static MonoType*
8768 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8769 {
8770         MonoReflectionAssemblyBuilder *abuilder;
8771         MonoType *type;
8772         int i;
8773
8774         mono_error_init (error);
8775         g_assert (assembly_is_dynamic (assembly));
8776         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8777         if (!abuilder)
8778                 return NULL;
8779
8780         /* Enumerate all modules */
8781
8782         type = NULL;
8783         if (abuilder->modules) {
8784                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8785                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8786                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8787                         if (type)
8788                                 break;
8789                         if (!mono_error_ok (error))
8790                                 return NULL;
8791                 }
8792         }
8793
8794         if (!type && abuilder->loaded_modules) {
8795                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8796                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8797                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8798                         if (type)
8799                                 break;
8800                         if (!mono_error_ok (error))
8801                                 return NULL;
8802                 }
8803         }
8804
8805         return type;
8806 }
8807         
8808 MonoType*
8809 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8810 {
8811         MonoType *type;
8812         MonoReflectionAssembly *assembly;
8813         GString *fullName;
8814         GList *mod;
8815
8816         mono_error_init (error);
8817
8818         if (image && image_is_dynamic (image))
8819                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8820         else {
8821                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8822         }
8823         return_val_if_nok (error, NULL);
8824
8825         if (type)
8826                 return type;
8827         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8828                 return NULL;
8829
8830         if (type_resolve) {
8831                 if (*type_resolve) 
8832                         return NULL;
8833                 else
8834                         *type_resolve = TRUE;
8835         }
8836         
8837         /* Reconstruct the type name */
8838         fullName = g_string_new ("");
8839         if (info->name_space && (info->name_space [0] != '\0'))
8840                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8841         else
8842                 g_string_printf (fullName, "%s", info->name);
8843         for (mod = info->nested; mod; mod = mod->next)
8844                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8845
8846         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8847         if (!is_ok (error)) {
8848                 g_string_free (fullName, TRUE);
8849                 return NULL;
8850         }
8851
8852         if (assembly) {
8853                 if (assembly_is_dynamic (assembly->assembly))
8854                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8855                                                                           info, ignorecase, error);
8856                 else
8857                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8858                                                                   info, ignorecase, error);
8859         }
8860         g_string_free (fullName, TRUE);
8861         return_val_if_nok (error, NULL);
8862         return type;
8863 }
8864
8865 void
8866 mono_reflection_free_type_info (MonoTypeNameParse *info)
8867 {
8868         g_list_free (info->modifiers);
8869         g_list_free (info->nested);
8870
8871         if (info->type_arguments) {
8872                 int i;
8873
8874                 for (i = 0; i < info->type_arguments->len; i++) {
8875                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8876
8877                         mono_reflection_free_type_info (subinfo);
8878                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8879                         g_free (subinfo);
8880                 }
8881
8882                 g_ptr_array_free (info->type_arguments, TRUE);
8883         }
8884 }
8885
8886 /*
8887  * mono_reflection_type_from_name:
8888  * @name: type name.
8889  * @image: a metadata context (can be NULL).
8890  *
8891  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8892  * it defaults to get the type from @image or, if @image is NULL or loading
8893  * from it fails, uses corlib.
8894  * 
8895  */
8896 MonoType*
8897 mono_reflection_type_from_name (char *name, MonoImage *image)
8898 {
8899         MonoError error;
8900         MonoType  *result = mono_reflection_type_from_name_checked (name, image, &error);
8901         mono_error_cleanup (&error);
8902         return result;
8903 }
8904
8905 /**
8906  * mono_reflection_type_from_name_checked:
8907  * @name: type name.
8908  * @image: a metadata context (can be NULL).
8909  * @error: set on errror.
8910  *
8911  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8912  * it defaults to get the type from @image or, if @image is NULL or loading
8913  * from it fails, uses corlib.  On failure returns NULL and sets @error.
8914  * 
8915  */
8916 MonoType*
8917 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8918 {
8919         MonoType *type = NULL;
8920         MonoTypeNameParse info;
8921         char *tmp;
8922
8923         mono_error_init (error);
8924         /* Make a copy since parse_type modifies its argument */
8925         tmp = g_strdup (name);
8926         
8927         /*g_print ("requested type %s\n", str);*/
8928         if (mono_reflection_parse_type (tmp, &info)) {
8929                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8930                 if (!is_ok (error)) {
8931                         g_free (tmp);
8932                         mono_reflection_free_type_info (&info);
8933                         return NULL;
8934                 }
8935         }
8936
8937         g_free (tmp);
8938         mono_reflection_free_type_info (&info);
8939         return type;
8940 }
8941
8942 /*
8943  * mono_reflection_get_token:
8944  *
8945  *   Return the metadata token of OBJ which should be an object
8946  * representing a metadata element.
8947  */
8948 guint32
8949 mono_reflection_get_token (MonoObject *obj)
8950 {
8951         MonoError error;
8952         guint32 result = mono_reflection_get_token_checked (obj, &error);
8953         mono_error_assert_ok (&error);
8954         return result;
8955 }
8956
8957 /**
8958  * mono_reflection_get_token_checked:
8959  * @obj: the object
8960  * @error: set on error
8961  *
8962  *   Return the metadata token of @obj which should be an object
8963  * representing a metadata element.  On failure sets @error.
8964  */
8965 guint32
8966 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8967 {
8968         MonoClass *klass;
8969         guint32 token = 0;
8970
8971         mono_error_init (error);
8972
8973         klass = obj->vtable->klass;
8974
8975         if (strcmp (klass->name, "MethodBuilder") == 0) {
8976                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8977
8978                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8979         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8980                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8981
8982                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8983         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8984                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8985
8986                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8987         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8988                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8989                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8990         } else if (strcmp (klass->name, "RuntimeType") == 0) {
8991                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8992                 return_val_if_nok (error, 0);
8993                 MonoClass *mc = mono_class_from_mono_type (type);
8994                 if (!mono_class_init (mc)) {
8995                         mono_error_set_for_class_failure (error, mc);
8996                         return 0;
8997                 }
8998
8999                 token = mc->type_token;
9000         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
9001                    strcmp (klass->name, "MonoMethod") == 0 ||
9002                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
9003                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
9004                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
9005                 if (m->method->is_inflated) {
9006                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
9007                         return inflated->declaring->token;
9008                 } else {
9009                         token = m->method->token;
9010                 }
9011         } else if (strcmp (klass->name, "MonoField") == 0) {
9012                 MonoReflectionField *f = (MonoReflectionField*)obj;
9013
9014                 if (is_field_on_inst (f->field)) {
9015                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
9016
9017                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
9018                                 int field_index = f->field - dgclass->fields;
9019                                 MonoObject *obj;
9020
9021                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
9022                                 obj = dgclass->field_objects [field_index];
9023                                 return mono_reflection_get_token_checked (obj, error);
9024                         }
9025                 }
9026                 token = mono_class_get_field_token (f->field);
9027         } else if (strcmp (klass->name, "MonoProperty") == 0) {
9028                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
9029
9030                 token = mono_class_get_property_token (p->property);
9031         } else if (strcmp (klass->name, "MonoEvent") == 0) {
9032                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
9033
9034                 token = mono_class_get_event_token (p->event);
9035         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
9036                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
9037                 MonoClass *member_class = mono_object_class (p->MemberImpl);
9038                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
9039
9040                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
9041         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
9042                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
9043
9044                 token = m->token;
9045         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
9046                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
9047         } else {
9048                 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
9049                                                 klass->name_space, klass->name);
9050                 return 0;
9051         }
9052
9053         return token;
9054 }
9055
9056 /*
9057  * Load the type with name @n on behalf of image @image.  On failure sets @error and returns NULL.
9058  * The @is_enum flag only affects the error message that's displayed on failure.
9059  */
9060 static MonoType*
9061 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
9062 {
9063         MonoError inner_error;
9064         MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
9065         if (!t) {
9066                 mono_error_set_type_load_name (error, g_strdup(n), NULL,
9067                                                "Could not load %s %s while decoding custom attribute: %s",
9068                                                is_enum ? "enum type": "type",
9069                                                n,
9070                                                mono_error_get_message (&inner_error));
9071                 mono_error_cleanup (&inner_error);
9072                 return NULL;
9073         }
9074         return t;
9075 }
9076
9077 static MonoClass*
9078 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
9079 {
9080         char *n;
9081         MonoType *t;
9082         int slen = mono_metadata_decode_value (p, &p);
9083
9084         mono_error_init (error);
9085
9086         n = (char *)g_memdup (p, slen + 1);
9087         n [slen] = 0;
9088         t = cattr_type_from_name (n, image, TRUE, error);
9089         g_free (n);
9090         return_val_if_nok (error, NULL);
9091         p += slen;
9092         *end = p;
9093         return mono_class_from_mono_type (t);
9094 }
9095
9096 static void*
9097 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
9098 {
9099         int slen, type = t->type;
9100         MonoClass *tklass = t->data.klass;
9101
9102         mono_error_init (error);
9103
9104 handle_enum:
9105         switch (type) {
9106         case MONO_TYPE_U1:
9107         case MONO_TYPE_I1:
9108         case MONO_TYPE_BOOLEAN: {
9109                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
9110                 *bval = *p;
9111                 *end = p + 1;
9112                 return bval;
9113         }
9114         case MONO_TYPE_CHAR:
9115         case MONO_TYPE_U2:
9116         case MONO_TYPE_I2: {
9117                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
9118                 *val = read16 (p);
9119                 *end = p + 2;
9120                 return val;
9121         }
9122 #if SIZEOF_VOID_P == 4
9123         case MONO_TYPE_U:
9124         case MONO_TYPE_I:
9125 #endif
9126         case MONO_TYPE_R4:
9127         case MONO_TYPE_U4:
9128         case MONO_TYPE_I4: {
9129                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9130                 *val = read32 (p);
9131                 *end = p + 4;
9132                 return val;
9133         }
9134 #if SIZEOF_VOID_P == 8
9135         case MONO_TYPE_U: /* error out instead? this should probably not happen */
9136         case MONO_TYPE_I:
9137 #endif
9138         case MONO_TYPE_U8:
9139         case MONO_TYPE_I8: {
9140                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9141                 *val = read64 (p);
9142                 *end = p + 8;
9143                 return val;
9144         }
9145         case MONO_TYPE_R8: {
9146                 double *val = (double *)g_malloc (sizeof (double));
9147                 readr8 (p, val);
9148                 *end = p + 8;
9149                 return val;
9150         }
9151         case MONO_TYPE_VALUETYPE:
9152                 if (t->data.klass->enumtype) {
9153                         type = mono_class_enum_basetype (t->data.klass)->type;
9154                         goto handle_enum;
9155                 } else {
9156                         MonoClass *k =  t->data.klass;
9157                         
9158                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9159                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9160                                 *val = read64 (p);
9161                                 *end = p + 8;
9162                                 return val;
9163                         }
9164                 }
9165                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9166                 break;
9167                 
9168         case MONO_TYPE_STRING:
9169                 if (*p == (char)0xFF) {
9170                         *end = p + 1;
9171                         return NULL;
9172                 }
9173                 slen = mono_metadata_decode_value (p, &p);
9174                 *end = p + slen;
9175                 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
9176         case MONO_TYPE_CLASS: {
9177                 MonoReflectionType *rt;
9178                 char *n;
9179                 MonoType *t;
9180                 if (*p == (char)0xFF) {
9181                         *end = p + 1;
9182                         return NULL;
9183                 }
9184 handle_type:
9185                 slen = mono_metadata_decode_value (p, &p);
9186                 n = (char *)g_memdup (p, slen + 1);
9187                 n [slen] = 0;
9188                 t = cattr_type_from_name (n, image, FALSE, error);
9189                 g_free (n);
9190                 return_val_if_nok (error, NULL);
9191                 *end = p + slen;
9192
9193                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9194                 if (!mono_error_ok (error))
9195                         return NULL;
9196
9197                 return rt;
9198         }
9199         case MONO_TYPE_OBJECT: {
9200                 char subt = *p++;
9201                 MonoObject *obj;
9202                 MonoClass *subc = NULL;
9203                 void *val;
9204
9205                 if (subt == 0x50) {
9206                         goto handle_type;
9207                 } else if (subt == 0x0E) {
9208                         type = MONO_TYPE_STRING;
9209                         goto handle_enum;
9210                 } else if (subt == 0x1D) {
9211                         MonoType simple_type = {{0}};
9212                         int etype = *p;
9213                         p ++;
9214
9215                         type = MONO_TYPE_SZARRAY;
9216                         if (etype == 0x50) {
9217                                 tklass = mono_defaults.systemtype_class;
9218                         } else if (etype == 0x55) {
9219                                 tklass = load_cattr_enum_type (image, p, &p, error);
9220                                 if (!mono_error_ok (error))
9221                                         return NULL;
9222                         } else {
9223                                 if (etype == 0x51)
9224                                         /* See Partition II, Appendix B3 */
9225                                         etype = MONO_TYPE_OBJECT;
9226                                 simple_type.type = (MonoTypeEnum)etype;
9227                                 tklass = mono_class_from_mono_type (&simple_type);
9228                         }
9229                         goto handle_enum;
9230                 } else if (subt == 0x55) {
9231                         char *n;
9232                         MonoType *t;
9233                         slen = mono_metadata_decode_value (p, &p);
9234                         n = (char *)g_memdup (p, slen + 1);
9235                         n [slen] = 0;
9236                         t = cattr_type_from_name (n, image, FALSE, error);
9237                         g_free (n);
9238                         return_val_if_nok (error, NULL);
9239                         p += slen;
9240                         subc = mono_class_from_mono_type (t);
9241                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9242                         MonoType simple_type = {{0}};
9243                         simple_type.type = (MonoTypeEnum)subt;
9244                         subc = mono_class_from_mono_type (&simple_type);
9245                 } else {
9246                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9247                 }
9248                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9249                 obj = NULL;
9250                 if (mono_error_ok (error)) {
9251                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
9252                         g_assert (!subc->has_references);
9253                         if (mono_error_ok (error))
9254                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9255                 }
9256
9257                 g_free (val);
9258                 return obj;
9259         }
9260         case MONO_TYPE_SZARRAY: {
9261                 MonoArray *arr;
9262                 guint32 i, alen, basetype;
9263                 alen = read32 (p);
9264                 p += 4;
9265                 if (alen == 0xffffffff) {
9266                         *end = p;
9267                         return NULL;
9268                 }
9269                 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
9270                 return_val_if_nok (error, NULL);
9271                 basetype = tklass->byval_arg.type;
9272                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9273                         basetype = mono_class_enum_basetype (tklass)->type;
9274                 switch (basetype)
9275                 {
9276                         case MONO_TYPE_U1:
9277                         case MONO_TYPE_I1:
9278                         case MONO_TYPE_BOOLEAN:
9279                                 for (i = 0; i < alen; i++) {
9280                                         MonoBoolean val = *p++;
9281                                         mono_array_set (arr, MonoBoolean, i, val);
9282                                 }
9283                                 break;
9284                         case MONO_TYPE_CHAR:
9285                         case MONO_TYPE_U2:
9286                         case MONO_TYPE_I2:
9287                                 for (i = 0; i < alen; i++) {
9288                                         guint16 val = read16 (p);
9289                                         mono_array_set (arr, guint16, i, val);
9290                                         p += 2;
9291                                 }
9292                                 break;
9293                         case MONO_TYPE_R4:
9294                         case MONO_TYPE_U4:
9295                         case MONO_TYPE_I4:
9296                                 for (i = 0; i < alen; i++) {
9297                                         guint32 val = read32 (p);
9298                                         mono_array_set (arr, guint32, i, val);
9299                                         p += 4;
9300                                 }
9301                                 break;
9302                         case MONO_TYPE_R8:
9303                                 for (i = 0; i < alen; i++) {
9304                                         double val;
9305                                         readr8 (p, &val);
9306                                         mono_array_set (arr, double, i, val);
9307                                         p += 8;
9308                                 }
9309                                 break;
9310                         case MONO_TYPE_U8:
9311                         case MONO_TYPE_I8:
9312                                 for (i = 0; i < alen; i++) {
9313                                         guint64 val = read64 (p);
9314                                         mono_array_set (arr, guint64, i, val);
9315                                         p += 8;
9316                                 }
9317                                 break;
9318                         case MONO_TYPE_CLASS:
9319                         case MONO_TYPE_OBJECT:
9320                         case MONO_TYPE_STRING:
9321                         case MONO_TYPE_SZARRAY:
9322                                 for (i = 0; i < alen; i++) {
9323                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9324                                         if (!mono_error_ok (error))
9325                                                 return NULL;
9326                                         mono_array_setref (arr, i, item);
9327                                 }
9328                                 break;
9329                         default:
9330                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9331                 }
9332                 *end=p;
9333                 return arr;
9334         }
9335         default:
9336                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9337         }
9338         return NULL;
9339 }
9340
9341 static MonoObject*
9342 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9343 {
9344         mono_error_init (error);
9345
9346         gboolean is_ref = type_is_reference (t);
9347
9348         void *val = load_cattr_value (image, t, p, end, error);
9349         if (!is_ok (error)) {
9350                 if (is_ref)
9351                         g_free (val);
9352                 return NULL;
9353         }
9354
9355         if (is_ref)
9356                 return (MonoObject*)val;
9357
9358         MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9359         g_free (val);
9360         return boxed;
9361 }
9362
9363 static MonoObject*
9364 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9365 {
9366         static MonoMethod *ctor;
9367         MonoObject *retval;
9368         void *params [2], *unboxed;
9369
9370         mono_error_init (error);
9371
9372         if (!ctor)
9373                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9374         
9375         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9376         return_val_if_nok (error, NULL);
9377
9378         params [1] = val;
9379         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9380         return_val_if_nok (error, NULL);
9381         unboxed = mono_object_unbox (retval);
9382
9383         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9384         return_val_if_nok (error, NULL);
9385
9386         return retval;
9387 }
9388
9389 static MonoObject*
9390 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9391 {
9392         static MonoMethod *ctor;
9393         MonoObject *retval;
9394         void *unboxed, *params [2];
9395
9396         mono_error_init (error);
9397
9398         if (!ctor)
9399                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9400
9401         params [0] = minfo;
9402         params [1] = typedarg;
9403         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9404         return_val_if_nok (error, NULL);
9405
9406         unboxed = mono_object_unbox (retval);
9407
9408         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9409         return_val_if_nok (error, NULL);
9410
9411         return retval;
9412 }
9413
9414 static gboolean
9415 type_is_reference (MonoType *type)
9416 {
9417         switch (type->type) {
9418         case MONO_TYPE_BOOLEAN:
9419         case MONO_TYPE_CHAR:
9420         case MONO_TYPE_U:
9421         case MONO_TYPE_I:
9422         case MONO_TYPE_U1:
9423         case MONO_TYPE_I1:
9424         case MONO_TYPE_U2:
9425         case MONO_TYPE_I2:
9426         case MONO_TYPE_U4:
9427         case MONO_TYPE_I4:
9428         case MONO_TYPE_U8:
9429         case MONO_TYPE_I8:
9430         case MONO_TYPE_R8:
9431         case MONO_TYPE_R4:
9432         case MONO_TYPE_VALUETYPE:
9433                 return FALSE;
9434         default:
9435                 return TRUE;
9436         }
9437 }
9438
9439 static void
9440 free_param_data (MonoMethodSignature *sig, void **params) {
9441         int i;
9442         for (i = 0; i < sig->param_count; ++i) {
9443                 if (!type_is_reference (sig->params [i]))
9444                         g_free (params [i]);
9445         }
9446 }
9447
9448 /*
9449  * Find the field index in the metadata FieldDef table.
9450  */
9451 static guint32
9452 find_field_index (MonoClass *klass, MonoClassField *field) {
9453         int i;
9454
9455         for (i = 0; i < klass->field.count; ++i) {
9456                 if (field == &klass->fields [i])
9457                         return klass->field.first + 1 + i;
9458         }
9459         return 0;
9460 }
9461
9462 /*
9463  * Find the property index in the metadata Property table.
9464  */
9465 static guint32
9466 find_property_index (MonoClass *klass, MonoProperty *property) {
9467         int i;
9468
9469         for (i = 0; i < klass->ext->property.count; ++i) {
9470                 if (property == &klass->ext->properties [i])
9471                         return klass->ext->property.first + 1 + i;
9472         }
9473         return 0;
9474 }
9475
9476 /*
9477  * Find the event index in the metadata Event table.
9478  */
9479 static guint32
9480 find_event_index (MonoClass *klass, MonoEvent *event) {
9481         int i;
9482
9483         for (i = 0; i < klass->ext->event.count; ++i) {
9484                 if (event == &klass->ext->events [i])
9485                         return klass->ext->event.first + 1 + i;
9486         }
9487         return 0;
9488 }
9489
9490 static MonoObject*
9491 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9492 {
9493         const char *p = (const char*)data;
9494         const char *named;
9495         guint32 i, j, num_named;
9496         MonoObject *attr;
9497         void *params_buf [32];
9498         void **params = NULL;
9499         MonoMethodSignature *sig;
9500
9501         mono_error_init (error);
9502
9503         mono_class_init (method->klass);
9504
9505         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9506                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9507                 return NULL;
9508         }
9509
9510         if (len == 0) {
9511                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9512                 if (!mono_error_ok (error)) return NULL;
9513
9514                 mono_runtime_invoke_checked (method, attr, NULL, error);
9515                 if (!mono_error_ok (error))
9516                         return NULL;
9517
9518                 return attr;
9519         }
9520
9521         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9522                 return NULL;
9523
9524         /*g_print ("got attr %s\n", method->klass->name);*/
9525
9526         sig = mono_method_signature (method);
9527         if (sig->param_count < 32) {
9528                 params = params_buf;
9529                 memset (params, 0, sizeof (void*) * sig->param_count);
9530         } else {
9531                 /* Allocate using GC so it gets GC tracking */
9532                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9533         }
9534
9535         /* skip prolog */
9536         p += 2;
9537         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9538                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9539                 if (!mono_error_ok (error))
9540                         goto fail;
9541         }
9542
9543         named = p;
9544         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9545         if (!mono_error_ok (error)) goto fail;
9546
9547         MonoObject *exc = NULL;
9548         mono_runtime_try_invoke (method, attr, params, &exc, error);
9549         if (!mono_error_ok (error))
9550                 goto fail;
9551         if (exc) {
9552                 mono_error_set_exception_instance (error, (MonoException*)exc);
9553                 goto fail;
9554         }
9555
9556         num_named = read16 (named);
9557         named += 2;
9558         for (j = 0; j < num_named; j++) {
9559                 gint name_len;
9560                 char *name, named_type, data_type;
9561                 named_type = *named++;
9562                 data_type = *named++; /* type of data */
9563                 if (data_type == MONO_TYPE_SZARRAY)
9564                         data_type = *named++;
9565                 if (data_type == MONO_TYPE_ENUM) {
9566                         gint type_len;
9567                         char *type_name;
9568                         type_len = mono_metadata_decode_blob_size (named, &named);
9569                         type_name = (char *)g_malloc (type_len + 1);
9570                         memcpy (type_name, named, type_len);
9571                         type_name [type_len] = 0;
9572                         named += type_len;
9573                         /* FIXME: lookup the type and check type consistency */
9574                         g_free (type_name);
9575                 }
9576                 name_len = mono_metadata_decode_blob_size (named, &named);
9577                 name = (char *)g_malloc (name_len + 1);
9578                 memcpy (name, named, name_len);
9579                 name [name_len] = 0;
9580                 named += name_len;
9581                 if (named_type == 0x53) {
9582                         MonoClassField *field;
9583                         void *val;
9584
9585                         /* how this fail is a blackbox */
9586                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9587                         if (!field) {
9588                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9589                                 g_free (name);
9590                                 goto fail;
9591                         }
9592
9593                         val = load_cattr_value (image, field->type, named, &named, error);
9594                         if (!mono_error_ok (error)) {
9595                                 g_free (name);
9596                                 if (!type_is_reference (field->type))
9597                                         g_free (val);
9598                                 goto fail;
9599                         }
9600
9601                         mono_field_set_value (attr, field, val);
9602                         if (!type_is_reference (field->type))
9603                                 g_free (val);
9604                 } else if (named_type == 0x54) {
9605                         MonoProperty *prop;
9606                         void *pparams [1];
9607                         MonoType *prop_type;
9608
9609                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9610
9611                         if (!prop) {
9612                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9613                                 g_free (name);
9614                                 goto fail;
9615                         }
9616
9617                         if (!prop->set) {
9618                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9619                                 g_free (name);
9620                                 goto fail;
9621                         }
9622
9623                         /* can we have more that 1 arg in a custom attr named property? */
9624                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9625                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9626
9627                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9628                         if (!mono_error_ok (error)) {
9629                                 g_free (name);
9630                                 if (!type_is_reference (prop_type))
9631                                         g_free (pparams [0]);
9632                                 goto fail;
9633                         }
9634
9635
9636                         mono_property_set_value_checked (prop, attr, pparams, error);
9637                         if (!type_is_reference (prop_type))
9638                                 g_free (pparams [0]);
9639                         if (!is_ok (error)) {
9640                                 g_free (name);
9641                                 goto fail;
9642                         }
9643                 }
9644                 g_free (name);
9645         }
9646
9647         free_param_data (method->signature, params);
9648         if (params != params_buf)
9649                 mono_gc_free_fixed (params);
9650
9651         return attr;
9652
9653 fail:
9654         free_param_data (method->signature, params);
9655         if (params != params_buf)
9656                 mono_gc_free_fixed (params);
9657         return NULL;
9658 }
9659         
9660 /*
9661  * mono_reflection_create_custom_attr_data_args:
9662  *
9663  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9664  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9665  * NAMED_ARG_INFO will contain information about the named arguments.
9666  */
9667 void
9668 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)
9669 {
9670         MonoArray *typedargs, *namedargs;
9671         MonoClass *attrklass;
9672         MonoDomain *domain;
9673         const char *p = (const char*)data;
9674         const char *named;
9675         guint32 i, j, num_named;
9676         CattrNamedArg *arginfo = NULL;
9677
9678         *typed_args = NULL;
9679         *named_args = NULL;
9680         *named_arg_info = NULL;
9681
9682         mono_error_init (error);
9683
9684         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9685                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9686                 return;
9687         }
9688
9689         mono_class_init (method->klass);
9690         
9691         domain = mono_domain_get ();
9692
9693         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9694                 return;
9695
9696         typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
9697         return_if_nok (error);
9698
9699         /* skip prolog */
9700         p += 2;
9701         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9702                 MonoObject *obj;
9703
9704                 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9705                 return_if_nok (error);
9706                 mono_array_setref (typedargs, i, obj);
9707         }
9708
9709         named = p;
9710         num_named = read16 (named);
9711         namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
9712         return_if_nok (error);
9713         named += 2;
9714         attrklass = method->klass;
9715
9716         arginfo = g_new0 (CattrNamedArg, num_named);
9717         *named_arg_info = arginfo;
9718
9719         for (j = 0; j < num_named; j++) {
9720                 gint name_len;
9721                 char *name, named_type, data_type;
9722                 named_type = *named++;
9723                 data_type = *named++; /* type of data */
9724                 if (data_type == MONO_TYPE_SZARRAY)
9725                         data_type = *named++;
9726                 if (data_type == MONO_TYPE_ENUM) {
9727                         gint type_len;
9728                         char *type_name;
9729                         type_len = mono_metadata_decode_blob_size (named, &named);
9730                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9731                                 goto fail;
9732
9733                         type_name = (char *)g_malloc (type_len + 1);
9734                         memcpy (type_name, named, type_len);
9735                         type_name [type_len] = 0;
9736                         named += type_len;
9737                         /* FIXME: lookup the type and check type consistency */
9738                         g_free (type_name);
9739                 }
9740                 name_len = mono_metadata_decode_blob_size (named, &named);
9741                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9742                         goto fail;
9743                 name = (char *)g_malloc (name_len + 1);
9744                 memcpy (name, named, name_len);
9745                 name [name_len] = 0;
9746                 named += name_len;
9747                 if (named_type == 0x53) {
9748                         MonoObject *obj;
9749                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9750
9751                         if (!field) {
9752                                 g_free (name);
9753                                 goto fail;
9754                         }
9755
9756                         arginfo [j].type = field->type;
9757                         arginfo [j].field = field;
9758
9759                         obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9760                         if (!is_ok (error)) {
9761                                 g_free (name);
9762                                 return;
9763                         }
9764                         mono_array_setref (namedargs, j, obj);
9765
9766                 } else if (named_type == 0x54) {
9767                         MonoObject *obj;
9768                         MonoType *prop_type;
9769                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9770
9771                         if (!prop || !prop->set) {
9772                                 g_free (name);
9773                                 goto fail;
9774                         }
9775
9776                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9777                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9778
9779                         arginfo [j].type = prop_type;
9780                         arginfo [j].prop = prop;
9781
9782                         obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9783                         if (!is_ok (error)) {
9784                                 g_free (name);
9785                                 return;
9786                         }
9787                         mono_array_setref (namedargs, j, obj);
9788                 }
9789                 g_free (name);
9790         }
9791
9792         *typed_args = typedargs;
9793         *named_args = namedargs;
9794         return;
9795 fail:
9796         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9797         g_free (arginfo);
9798         *named_arg_info = NULL;
9799 }
9800
9801 static gboolean
9802 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
9803 {
9804         MonoDomain *domain;
9805         MonoArray *typedargs, *namedargs;
9806         MonoImage *image;
9807         MonoMethod *method;
9808         CattrNamedArg *arginfo = NULL;
9809         int i;
9810
9811         mono_error_init (error);
9812
9813         *ctor_args = NULL;
9814         *named_args = NULL;
9815
9816         if (len == 0)
9817                 return TRUE;
9818
9819         image = assembly->assembly->image;
9820         method = ref_method->method;
9821         domain = mono_object_domain (ref_method);
9822
9823         if (!mono_class_init (method->klass)) {
9824                 mono_error_set_for_class_failure (error, method->klass);
9825                 goto leave;
9826         }
9827
9828         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
9829         if (!is_ok (error))
9830                 goto leave;
9831
9832         if (!typedargs || !namedargs)
9833                 goto leave;
9834
9835         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9836                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9837                 MonoObject *typedarg;
9838
9839                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
9840                 if (!is_ok (error))
9841                         goto leave;
9842                 mono_array_setref (typedargs, i, typedarg);
9843         }
9844
9845         for (i = 0; i < mono_array_length (namedargs); ++i) {
9846                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9847                 MonoObject *typedarg, *namedarg, *minfo;
9848
9849                 if (arginfo [i].prop) {
9850                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
9851                         if (!minfo)
9852                                 goto leave;
9853                 } else {
9854                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
9855                         if (!is_ok (error))
9856                                 goto leave;
9857                 }
9858
9859                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
9860                 if (!is_ok (error))
9861                         goto leave;
9862                 namedarg = create_cattr_named_arg (minfo, typedarg, error);
9863                 if (!is_ok (error))
9864                         goto leave;
9865
9866                 mono_array_setref (namedargs, i, namedarg);
9867         }
9868
9869         *ctor_args = typedargs;
9870         *named_args = namedargs;
9871
9872 leave:
9873         g_free (arginfo);
9874         return mono_error_ok (error);
9875 }
9876
9877 void
9878 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9879 {
9880         MonoError error;
9881         (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
9882         mono_error_set_pending_exception (&error);
9883 }
9884
9885 static MonoObject*
9886 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9887 {
9888         static MonoMethod *ctor;
9889
9890         MonoDomain *domain;
9891         MonoObject *attr;
9892         void *params [4];
9893
9894         mono_error_init (error);
9895
9896         g_assert (image->assembly);
9897
9898         if (!ctor)
9899                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9900
9901         domain = mono_domain_get ();
9902         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9903         return_val_if_nok (error, NULL);
9904         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9905         return_val_if_nok (error, NULL);
9906         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9907         return_val_if_nok (error, NULL);
9908         params [2] = (gpointer)&cattr->data;
9909         params [3] = &cattr->data_size;
9910
9911         mono_runtime_invoke_checked (ctor, attr, params, error);
9912         return_val_if_nok (error, NULL);
9913         return attr;
9914 }
9915
9916 static MonoArray*
9917 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9918 {
9919         MonoArray *result;
9920         MonoObject *attr;
9921         int i, n;
9922
9923         mono_error_init (error);
9924
9925         for (i = 0; i < cinfo->num_attrs; ++i) {
9926                 MonoCustomAttrEntry *centry = &cinfo->attrs[i];
9927                 if (!centry->ctor) {
9928                         /* The cattr type is not finished yet */
9929                         /* We should include the type name but cinfo doesn't contain it */
9930                         mono_error_set_type_load_name (error, NULL, NULL, "Custom attribute constructor is null because the custom attribute type is not finished yet.");
9931                         return NULL;
9932                 }
9933         }
9934
9935         n = 0;
9936         if (attr_klass) {
9937                 for (i = 0; i < cinfo->num_attrs; ++i) {
9938                         MonoMethod *ctor = cinfo->attrs[i].ctor;
9939                         g_assert (ctor);
9940                         if (mono_class_is_assignable_from (attr_klass, ctor->klass))
9941                                 n++;
9942                 }
9943         } else {
9944                 n = cinfo->num_attrs;
9945         }
9946
9947         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
9948         return_val_if_nok (error, NULL);
9949         n = 0;
9950         for (i = 0; i < cinfo->num_attrs; ++i) {
9951                 MonoCustomAttrEntry *centry = &cinfo->attrs [i];
9952                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, centry->ctor->klass)) {
9953                         attr = create_custom_attr (cinfo->image, centry->ctor, centry->data, centry->data_size, error);
9954                         if (!mono_error_ok (error))
9955                                 return result;
9956                         mono_array_setref (result, n, attr);
9957                         n ++;
9958                 }
9959         }
9960         return result;
9961 }
9962
9963 MonoArray*
9964 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9965 {
9966         MonoError error;
9967         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9968         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9969
9970         return result;
9971 }
9972
9973 static MonoArray*
9974 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9975 {
9976         MonoArray *result;
9977         MonoObject *attr;
9978         int i;
9979         
9980         mono_error_init (error);
9981         result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
9982         return_val_if_nok (error, NULL);
9983         for (i = 0; i < cinfo->num_attrs; ++i) {
9984                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9985                 return_val_if_nok (error, NULL);
9986                 mono_array_setref (result, i, attr);
9987         }
9988         return result;
9989 }
9990
9991 /**
9992  * mono_custom_attrs_from_index:
9993  *
9994  * Returns: NULL if no attributes are found or if a loading error occurs.
9995  */
9996 MonoCustomAttrInfo*
9997 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9998 {
9999         MonoError error;
10000         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
10001         mono_error_cleanup (&error);
10002         return result;
10003 }
10004 /**
10005  * mono_custom_attrs_from_index_checked:
10006  *
10007  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
10008  */
10009 MonoCustomAttrInfo*
10010 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
10011 {
10012         guint32 mtoken, i, len;
10013         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
10014         MonoTableInfo *ca;
10015         MonoCustomAttrInfo *ainfo;
10016         GList *tmp, *list = NULL;
10017         const char *data;
10018         MonoCustomAttrEntry* attr;
10019
10020         mono_error_init (error);
10021
10022         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
10023
10024         i = mono_metadata_custom_attrs_from_index (image, idx);
10025         if (!i)
10026                 return NULL;
10027         i --;
10028         while (i < ca->rows) {
10029                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
10030                         break;
10031                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
10032                 ++i;
10033         }
10034         len = g_list_length (list);
10035         if (!len)
10036                 return NULL;
10037         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
10038         ainfo->num_attrs = len;
10039         ainfo->image = image;
10040         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
10041                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
10042                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
10043                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
10044                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
10045                         mtoken |= MONO_TOKEN_METHOD_DEF;
10046                         break;
10047                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
10048                         mtoken |= MONO_TOKEN_MEMBER_REF;
10049                         break;
10050                 default:
10051                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
10052                         break;
10053                 }
10054                 attr = &ainfo->attrs [i - 1];
10055                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
10056                 if (!attr->ctor) {
10057                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
10058                         g_list_free (list);
10059                         g_free (ainfo);
10060                         return NULL;
10061                 }
10062
10063                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
10064                         /*FIXME raising an exception here doesn't make any sense*/
10065                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
10066                         g_list_free (list);
10067                         g_free (ainfo);
10068                         return NULL;
10069                 }
10070                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
10071                 attr->data_size = mono_metadata_decode_value (data, &data);
10072                 attr->data = (guchar*)data;
10073         }
10074         g_list_free (list);
10075
10076         return ainfo;
10077 }
10078
10079 MonoCustomAttrInfo*
10080 mono_custom_attrs_from_method (MonoMethod *method)
10081 {
10082         MonoError error;
10083         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
10084         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10085         return result;
10086 }
10087
10088 MonoCustomAttrInfo*
10089 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
10090 {
10091         guint32 idx;
10092
10093         mono_error_init (error);
10094
10095         /*
10096          * An instantiated method has the same cattrs as the generic method definition.
10097          *
10098          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10099          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10100          */
10101         if (method->is_inflated)
10102                 method = ((MonoMethodInflated *) method)->declaring;
10103         
10104         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
10105                 return lookup_custom_attr (method->klass->image, method);
10106
10107         if (!method->token)
10108                 /* Synthetic methods */
10109                 return NULL;
10110
10111         idx = mono_method_get_index (method);
10112         idx <<= MONO_CUSTOM_ATTR_BITS;
10113         idx |= MONO_CUSTOM_ATTR_METHODDEF;
10114         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
10115 }
10116
10117 MonoCustomAttrInfo*
10118 mono_custom_attrs_from_class (MonoClass *klass)
10119 {
10120         MonoError error;
10121         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
10122         mono_error_cleanup (&error);
10123         return result;
10124 }
10125
10126 MonoCustomAttrInfo*
10127 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
10128 {
10129         guint32 idx;
10130
10131         mono_error_init (error);
10132
10133         if (klass->generic_class)
10134                 klass = klass->generic_class->container_class;
10135
10136         if (image_is_dynamic (klass->image))
10137                 return lookup_custom_attr (klass->image, klass);
10138
10139         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
10140                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
10141                 idx <<= MONO_CUSTOM_ATTR_BITS;
10142                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10143         } else {
10144                 idx = mono_metadata_token_index (klass->type_token);
10145                 idx <<= MONO_CUSTOM_ATTR_BITS;
10146                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10147         }
10148         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10149 }
10150
10151 MonoCustomAttrInfo*
10152 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10153 {
10154         MonoError error;
10155         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10156         mono_error_cleanup (&error);
10157         return result;
10158 }
10159
10160 MonoCustomAttrInfo*
10161 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10162 {
10163         guint32 idx;
10164         
10165         mono_error_init (error);
10166
10167         if (image_is_dynamic (assembly->image))
10168                 return lookup_custom_attr (assembly->image, assembly);
10169         idx = 1; /* there is only one assembly */
10170         idx <<= MONO_CUSTOM_ATTR_BITS;
10171         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10172         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10173 }
10174
10175 static MonoCustomAttrInfo*
10176 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10177 {
10178         guint32 idx;
10179         
10180         if (image_is_dynamic (image))
10181                 return lookup_custom_attr (image, image);
10182         idx = 1; /* there is only one module */
10183         idx <<= MONO_CUSTOM_ATTR_BITS;
10184         idx |= MONO_CUSTOM_ATTR_MODULE;
10185         return mono_custom_attrs_from_index_checked (image, idx, error);
10186 }
10187
10188 MonoCustomAttrInfo*
10189 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10190 {
10191         MonoError error;
10192         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10193         mono_error_cleanup (&error);
10194         return result;
10195 }
10196
10197 MonoCustomAttrInfo*
10198 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10199 {
10200         guint32 idx;
10201         
10202         if (image_is_dynamic (klass->image)) {
10203                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10204                 return lookup_custom_attr (klass->image, property);
10205         }
10206         idx = find_property_index (klass, property);
10207         idx <<= MONO_CUSTOM_ATTR_BITS;
10208         idx |= MONO_CUSTOM_ATTR_PROPERTY;
10209         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10210 }
10211
10212 MonoCustomAttrInfo*
10213 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10214 {
10215         MonoError error;
10216         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10217         mono_error_cleanup (&error);
10218         return result;
10219 }
10220
10221 MonoCustomAttrInfo*
10222 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10223 {
10224         guint32 idx;
10225         
10226         if (image_is_dynamic (klass->image)) {
10227                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10228                 return lookup_custom_attr (klass->image, event);
10229         }
10230         idx = find_event_index (klass, event);
10231         idx <<= MONO_CUSTOM_ATTR_BITS;
10232         idx |= MONO_CUSTOM_ATTR_EVENT;
10233         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10234 }
10235
10236 MonoCustomAttrInfo*
10237 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10238 {
10239         MonoError error;
10240         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10241         mono_error_cleanup (&error);
10242         return result;
10243 }
10244
10245 MonoCustomAttrInfo*
10246 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10247 {
10248         guint32 idx;
10249         mono_error_init (error);
10250
10251         if (image_is_dynamic (klass->image)) {
10252                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10253                 return lookup_custom_attr (klass->image, field);
10254         }
10255         idx = find_field_index (klass, field);
10256         idx <<= MONO_CUSTOM_ATTR_BITS;
10257         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10258         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10259 }
10260
10261 /**
10262  * mono_custom_attrs_from_param:
10263  * @method: handle to the method that we want to retrieve custom parameter information from
10264  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10265  *
10266  * The result must be released with mono_custom_attrs_free().
10267  *
10268  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10269  */
10270 MonoCustomAttrInfo*
10271 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10272 {
10273         MonoError error;
10274         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10275         mono_error_cleanup (&error);
10276         return result;
10277 }
10278
10279 /**
10280  * mono_custom_attrs_from_param_checked:
10281  * @method: handle to the method that we want to retrieve custom parameter information from
10282  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10283  * @error: set on error
10284  *
10285  * The result must be released with mono_custom_attrs_free().
10286  *
10287  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
10288  */
10289 MonoCustomAttrInfo*
10290 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10291 {
10292         MonoTableInfo *ca;
10293         guint32 i, idx, method_index;
10294         guint32 param_list, param_last, param_pos, found;
10295         MonoImage *image;
10296         MonoReflectionMethodAux *aux;
10297
10298         mono_error_init (error);
10299
10300         /*
10301          * An instantiated method has the same cattrs as the generic method definition.
10302          *
10303          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10304          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10305          */
10306         if (method->is_inflated)
10307                 method = ((MonoMethodInflated *) method)->declaring;
10308
10309         if (image_is_dynamic (method->klass->image)) {
10310                 MonoCustomAttrInfo *res, *ainfo;
10311                 int size;
10312
10313                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10314                 if (!aux || !aux->param_cattr)
10315                         return NULL;
10316
10317                 /* Need to copy since it will be freed later */
10318                 ainfo = aux->param_cattr [param];
10319                 if (!ainfo)
10320                         return NULL;
10321                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10322                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10323                 memcpy (res, ainfo, size);
10324                 return res;
10325         }
10326
10327         image = method->klass->image;
10328         method_index = mono_method_get_index (method);
10329         if (!method_index)
10330                 return NULL;
10331         ca = &image->tables [MONO_TABLE_METHOD];
10332
10333         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10334         if (method_index == ca->rows) {
10335                 ca = &image->tables [MONO_TABLE_PARAM];
10336                 param_last = ca->rows + 1;
10337         } else {
10338                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10339                 ca = &image->tables [MONO_TABLE_PARAM];
10340         }
10341         found = FALSE;
10342         for (i = param_list; i < param_last; ++i) {
10343                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10344                 if (param_pos == param) {
10345                         found = TRUE;
10346                         break;
10347                 }
10348         }
10349         if (!found)
10350                 return NULL;
10351         idx = i;
10352         idx <<= MONO_CUSTOM_ATTR_BITS;
10353         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10354         return mono_custom_attrs_from_index_checked (image, idx, error);
10355 }
10356
10357 gboolean
10358 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10359 {
10360         int i;
10361         for (i = 0; i < ainfo->num_attrs; ++i) {
10362                 MonoClass *klass = ainfo->attrs [i].ctor->klass;
10363                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10364                         return TRUE;
10365         }
10366         return FALSE;
10367 }
10368
10369 MonoObject*
10370 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10371 {
10372         MonoError error;
10373         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10374         mono_error_assert_ok (&error); /*FIXME proper error handling*/
10375         return res;
10376 }
10377
10378 MonoObject*
10379 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10380 {
10381         int i, attr_index;
10382         MonoArray *attrs;
10383
10384         mono_error_init (error);
10385
10386         attr_index = -1;
10387         for (i = 0; i < ainfo->num_attrs; ++i) {
10388                 MonoClass *klass = ainfo->attrs [i].ctor->klass;
10389                 if (mono_class_has_parent (klass, attr_klass)) {
10390                         attr_index = i;
10391                         break;
10392                 }
10393         }
10394         if (attr_index == -1)
10395                 return NULL;
10396
10397         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10398         if (!mono_error_ok (error))
10399                 return NULL;
10400         return mono_array_get (attrs, MonoObject*, attr_index);
10401 }
10402
10403 /*
10404  * mono_reflection_get_custom_attrs_info:
10405  * @obj: a reflection object handle
10406  *
10407  * Return the custom attribute info for attributes defined for the
10408  * reflection handle @obj. The objects.
10409  *
10410  * FIXME this function leaks like a sieve for SRE objects.
10411  */
10412 MonoCustomAttrInfo*
10413 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10414 {
10415         MonoError error;
10416         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10417         mono_error_assert_ok (&error);
10418         return result;
10419 }
10420
10421 /**
10422  * mono_reflection_get_custom_attrs_info_checked:
10423  * @obj: a reflection object handle
10424  * @error: set on error
10425  *
10426  * Return the custom attribute info for attributes defined for the
10427  * reflection handle @obj. The objects.
10428  *
10429  * On failure returns NULL and sets @error.
10430  *
10431  * FIXME this function leaks like a sieve for SRE objects.
10432  */
10433 MonoCustomAttrInfo*
10434 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10435 {
10436         MonoClass *klass;
10437         MonoCustomAttrInfo *cinfo = NULL;
10438         
10439         mono_error_init (error);
10440
10441         klass = obj->vtable->klass;
10442         if (klass == mono_defaults.runtimetype_class) {
10443                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10444                 return_val_if_nok (error, NULL);
10445                 klass = mono_class_from_mono_type (type);
10446                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10447                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10448                 return_val_if_nok (error, NULL);
10449         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10450                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10451                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10452                 return_val_if_nok (error, NULL);
10453         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10454                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10455                 cinfo = mono_custom_attrs_from_module (module->image, error);
10456                 return_val_if_nok (error, NULL);
10457         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10458                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10459                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10460                 return_val_if_nok (error, NULL);
10461         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10462                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10463                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10464                 return_val_if_nok (error, NULL);
10465         } else if (strcmp ("MonoField", klass->name) == 0) {
10466                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10467                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10468                 return_val_if_nok (error, NULL);
10469         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10470                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10471                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10472                 return_val_if_nok (error, NULL);
10473         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10474                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10475                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10476                 return_val_if_nok (error, NULL);
10477         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10478                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10479                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10480                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10481                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10482                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10483                         return_val_if_nok (error, NULL);
10484                 } else if (is_sr_mono_property (member_class)) {
10485                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10486                         MonoMethod *method;
10487                         if (!(method = prop->property->get))
10488                                 method = prop->property->set;
10489                         g_assert (method);
10490
10491                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10492                         return_val_if_nok (error, NULL);
10493                 } 
10494 #ifndef DISABLE_REFLECTION_EMIT
10495                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10496                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10497                         return_val_if_nok (error, NULL);
10498                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10499                         return_val_if_nok (error, NULL);
10500                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10501                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10502                         MonoMethod *method = NULL;
10503                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10504                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10505                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10506                                 method = ((MonoReflectionMethod *)c->cb)->method;
10507                         else
10508                                 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));
10509
10510                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10511                         return_val_if_nok (error, NULL);
10512                 } 
10513 #endif
10514                 else {
10515                         char *type_name = mono_type_get_full_name (member_class);
10516                         mono_error_set_not_supported (error,
10517                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10518                                                       type_name);
10519                         g_free (type_name);
10520                         return NULL;
10521                 }
10522         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10523                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10524                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10525         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10526                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10527                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10528         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10529                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10530                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10531         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10532                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10533                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10534         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10535                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10536                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10537         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10538                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10539                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10540         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10541                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10542                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10543                 return_val_if_nok (error, NULL);
10544         } else { /* handle other types here... */
10545                 g_error ("get custom attrs not yet supported for %s", klass->name);
10546         }
10547
10548         return cinfo;
10549 }
10550
10551 /*
10552  * mono_reflection_get_custom_attrs_by_type:
10553  * @obj: a reflection object handle
10554  *
10555  * Return an array with all the custom attributes defined of the
10556  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10557  * of that type are returned. The objects are fully build. Return NULL if a loading error
10558  * occurs.
10559  */
10560 MonoArray*
10561 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10562 {
10563         MonoArray *result;
10564         MonoCustomAttrInfo *cinfo;
10565
10566         mono_error_init (error);
10567
10568         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10569         return_val_if_nok (error, NULL);
10570         if (cinfo) {
10571                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10572                 if (!cinfo->cached)
10573                         mono_custom_attrs_free (cinfo);
10574                 if (!result)
10575                         return NULL;
10576         } else {
10577                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
10578         }
10579
10580         return result;
10581 }
10582
10583 /*
10584  * mono_reflection_get_custom_attrs:
10585  * @obj: a reflection object handle
10586  *
10587  * Return an array with all the custom attributes defined of the
10588  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10589  * occurs.
10590  */
10591 MonoArray*
10592 mono_reflection_get_custom_attrs (MonoObject *obj)
10593 {
10594         MonoError error;
10595
10596         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10597 }
10598
10599 /*
10600  * mono_reflection_get_custom_attrs_data:
10601  * @obj: a reflection obj handle
10602  *
10603  * Returns an array of System.Reflection.CustomAttributeData,
10604  * which include information about attributes reflected on
10605  * types loaded using the Reflection Only methods
10606  */
10607 MonoArray*
10608 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10609 {
10610         MonoError error;
10611         MonoArray* result;
10612         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10613         mono_error_cleanup (&error);
10614         return result;
10615 }
10616
10617 /*
10618  * mono_reflection_get_custom_attrs_data_checked:
10619  * @obj: a reflection obj handle
10620  * @error: set on error
10621  *
10622  * Returns an array of System.Reflection.CustomAttributeData,
10623  * which include information about attributes reflected on
10624  * types loaded using the Reflection Only methods
10625  */
10626 MonoArray*
10627 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10628 {
10629         MonoArray *result;
10630         MonoCustomAttrInfo *cinfo;
10631
10632         mono_error_init (error);
10633
10634         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10635         return_val_if_nok (error, NULL);
10636         if (cinfo) {
10637                 result = mono_custom_attrs_data_construct (cinfo, error);
10638                 if (!cinfo->cached)
10639                         mono_custom_attrs_free (cinfo);
10640                 return_val_if_nok (error, NULL);
10641         } else 
10642                 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
10643
10644         return result;
10645 }
10646
10647 static MonoReflectionType*
10648 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10649 {
10650         static MonoMethod *method_get_underlying_system_type = NULL;
10651         MonoReflectionType *rt;
10652         MonoMethod *usertype_method;
10653
10654         mono_error_init (error);
10655
10656         if (!method_get_underlying_system_type)
10657                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10658
10659         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10660
10661         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10662
10663         return rt;
10664 }
10665
10666
10667 static gboolean
10668 is_corlib_type (MonoClass *klass)
10669 {
10670         return klass->image == mono_defaults.corlib;
10671 }
10672
10673 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10674         static MonoClass *cached_class; \
10675         if (cached_class) \
10676                 return cached_class == _class; \
10677         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10678                 cached_class = _class; \
10679                 return TRUE; \
10680         } \
10681         return FALSE; \
10682 } while (0) \
10683
10684
10685 #ifndef DISABLE_REFLECTION_EMIT
10686 static gboolean
10687 is_sre_array (MonoClass *klass)
10688 {
10689         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10690 }
10691
10692 static gboolean
10693 is_sre_byref (MonoClass *klass)
10694 {
10695         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10696 }
10697
10698 static gboolean
10699 is_sre_pointer (MonoClass *klass)
10700 {
10701         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10702 }
10703
10704 static gboolean
10705 is_sre_generic_instance (MonoClass *klass)
10706 {
10707         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10708 }
10709
10710 static gboolean
10711 is_sre_type_builder (MonoClass *klass)
10712 {
10713         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10714 }
10715
10716 static gboolean
10717 is_sre_method_builder (MonoClass *klass)
10718 {
10719         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10720 }
10721
10722 static gboolean
10723 is_sre_ctor_builder (MonoClass *klass)
10724 {
10725         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10726 }
10727
10728 static gboolean
10729 is_sre_field_builder (MonoClass *klass)
10730 {
10731         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10732 }
10733
10734 static gboolean
10735 is_sre_method_on_tb_inst (MonoClass *klass)
10736 {
10737         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10738 }
10739
10740 static gboolean
10741 is_sre_ctor_on_tb_inst (MonoClass *klass)
10742 {
10743         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10744 }
10745
10746 MonoType*
10747 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10748 {
10749         MonoClass *klass;
10750         mono_error_init (error);
10751
10752         if (!ref)
10753                 return NULL;
10754         if (ref->type)
10755                 return ref->type;
10756
10757         if (is_usertype (ref)) {
10758                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10759                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10760                         return NULL;
10761                 if (ref->type)
10762                         return ref->type;
10763         }
10764
10765         klass = mono_object_class (ref);
10766
10767         if (is_sre_array (klass)) {
10768                 MonoType *res;
10769                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10770                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10771                 return_val_if_nok (error, NULL);
10772                 g_assert (base);
10773                 if (sre_array->rank == 0) //single dimentional array
10774                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10775                 else
10776                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10777                 sre_array->type.type = res;
10778                 return res;
10779         } else if (is_sre_byref (klass)) {
10780                 MonoType *res;
10781                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10782                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10783                 return_val_if_nok (error, NULL);
10784                 g_assert (base);
10785                 res = &mono_class_from_mono_type (base)->this_arg;
10786                 sre_byref->type.type = res;
10787                 return res;
10788         } else if (is_sre_pointer (klass)) {
10789                 MonoType *res;
10790                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10791                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10792                 return_val_if_nok (error, NULL);
10793                 g_assert (base);
10794                 res = &mono_ptr_class_get (base)->byval_arg;
10795                 sre_pointer->type.type = res;
10796                 return res;
10797         } else if (is_sre_generic_instance (klass)) {
10798                 MonoType *res, **types;
10799                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10800                 int i, count;
10801
10802                 count = mono_array_length (gclass->type_arguments);
10803                 types = g_new0 (MonoType*, count);
10804                 for (i = 0; i < count; ++i) {
10805                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10806                         types [i] = mono_reflection_type_get_handle (t, error);
10807                         if (!types[i] || !is_ok (error)) {
10808                                 g_free (types);
10809                                 return NULL;
10810                         }
10811                 }
10812
10813                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10814                 g_free (types);
10815                 g_assert (res);
10816                 gclass->type.type = res;
10817                 return res;
10818         }
10819
10820         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10821         return NULL;
10822 }
10823
10824 void
10825 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10826 {
10827         MonoError error;
10828         mono_reflection_type_get_handle (type, &error);
10829         mono_error_set_pending_exception (&error);
10830 }
10831
10832 static gboolean
10833 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10834 {
10835         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10836         MonoClass *klass;
10837
10838         mono_error_init (error);
10839
10840         MonoType *res = mono_reflection_type_get_handle (type, error);
10841
10842         if (!res && is_ok (error)) {
10843                 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10844         }
10845         return_val_if_nok (error, FALSE);
10846
10847         klass = mono_class_from_mono_type (res);
10848
10849         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10850         mono_domain_lock (domain);
10851
10852         if (!image_is_dynamic (klass->image)) {
10853                 mono_class_setup_supertypes (klass);
10854         } else {
10855                 if (!domain->type_hash)
10856                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10857                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10858                 mono_g_hash_table_insert (domain->type_hash, res, type);
10859         }
10860         mono_domain_unlock (domain);
10861         mono_loader_unlock ();
10862
10863         return TRUE;
10864 }
10865
10866 void
10867 mono_reflection_register_with_runtime (MonoReflectionType *type)
10868 {
10869         MonoError error;
10870         (void) reflection_register_with_runtime (type, &error);
10871         mono_error_set_pending_exception (&error);
10872 }
10873
10874 /**
10875  * LOCKING: Assumes the loader lock is held.
10876  */
10877 static MonoMethodSignature*
10878 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10879         MonoMethodSignature *sig;
10880         int count, i;
10881
10882         mono_error_init (error);
10883
10884         count = parameters? mono_array_length (parameters): 0;
10885
10886         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10887         sig->param_count = count;
10888         sig->sentinelpos = -1; /* FIXME */
10889         for (i = 0; i < count; ++i) {
10890                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10891                 if (!is_ok (error)) {
10892                         image_g_free (image, sig);
10893                         return NULL;
10894                 }
10895         }
10896         return sig;
10897 }
10898
10899 /**
10900  * LOCKING: Assumes the loader lock is held.
10901  */
10902 static MonoMethodSignature*
10903 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10904         MonoMethodSignature *sig;
10905
10906         mono_error_init (error);
10907
10908         sig = parameters_to_signature (image, ctor->parameters, error);
10909         return_val_if_nok (error, NULL);
10910         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10911         sig->ret = &mono_defaults.void_class->byval_arg;
10912         return sig;
10913 }
10914
10915 /**
10916  * LOCKING: Assumes the loader lock is held.
10917  */
10918 static MonoMethodSignature*
10919 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10920         MonoMethodSignature *sig;
10921
10922         mono_error_init (error);
10923
10924         sig = parameters_to_signature (image, method->parameters, error);
10925         return_val_if_nok (error, NULL);
10926         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10927         if (method->rtype) {
10928                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10929                 if (!is_ok (error)) {
10930                         image_g_free (image, sig);
10931                         return NULL;
10932                 }
10933         } else {
10934                 sig->ret = &mono_defaults.void_class->byval_arg;
10935         }
10936         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10937         return sig;
10938 }
10939
10940 static MonoMethodSignature*
10941 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10942         MonoMethodSignature *sig;
10943
10944         mono_error_init (error);
10945
10946         sig = parameters_to_signature (NULL, method->parameters, error);
10947         return_val_if_nok (error, NULL);
10948         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10949         if (method->rtype) {
10950                 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10951                 if (!is_ok (error)) {
10952                         g_free (sig);
10953                         return NULL;
10954                 }
10955         } else {
10956                 sig->ret = &mono_defaults.void_class->byval_arg;
10957         }
10958         sig->generic_param_count = 0;
10959         return sig;
10960 }
10961
10962 static void
10963 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10964 {
10965         mono_error_init (error);
10966         MonoClass *klass = mono_object_class (prop);
10967         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10968                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10969                 *name = mono_string_to_utf8_checked (pb->name, error);
10970                 return_if_nok (error);
10971                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10972         } else {
10973                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10974                 *name = g_strdup (p->property->name);
10975                 if (p->property->get)
10976                         *type = mono_method_signature (p->property->get)->ret;
10977                 else
10978                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10979         }
10980 }
10981
10982 static void
10983 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10984 {
10985         mono_error_init (error);
10986         MonoClass *klass = mono_object_class (field);
10987         if (strcmp (klass->name, "FieldBuilder") == 0) {
10988                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10989                 *name = mono_string_to_utf8_checked (fb->name, error);
10990                 return_if_nok (error);
10991                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10992         } else {
10993                 MonoReflectionField *f = (MonoReflectionField *)field;
10994                 *name = g_strdup (mono_field_get_name (f->field));
10995                 *type = f->field->type;
10996         }
10997 }
10998
10999 #else /* DISABLE_REFLECTION_EMIT */
11000
11001 void
11002 mono_reflection_register_with_runtime (MonoReflectionType *type)
11003 {
11004         /* This is empty */
11005 }
11006
11007 static gboolean
11008 is_sre_type_builder (MonoClass *klass)
11009 {
11010         return FALSE;
11011 }
11012
11013 static gboolean
11014 is_sre_generic_instance (MonoClass *klass)
11015 {
11016         return FALSE;
11017 }
11018
11019 static void
11020 init_type_builder_generics (MonoObject *type, MonoError *error)
11021 {
11022         mono_error_init (error);
11023 }
11024
11025 #endif /* !DISABLE_REFLECTION_EMIT */
11026
11027
11028 static gboolean
11029 is_sr_mono_field (MonoClass *klass)
11030 {
11031         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
11032 }
11033
11034 static gboolean
11035 is_sr_mono_property (MonoClass *klass)
11036 {
11037         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
11038 }
11039
11040 static gboolean
11041 is_sr_mono_method (MonoClass *klass)
11042 {
11043         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
11044 }
11045
11046 static gboolean
11047 is_sr_mono_cmethod (MonoClass *klass)
11048 {
11049         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
11050 }
11051
11052 static gboolean
11053 is_sr_mono_generic_method (MonoClass *klass)
11054 {
11055         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
11056 }
11057
11058 static gboolean
11059 is_sr_mono_generic_cmethod (MonoClass *klass)
11060 {
11061         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
11062 }
11063
11064 gboolean
11065 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
11066 {
11067         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
11068 }
11069
11070 static gboolean
11071 is_usertype (MonoReflectionType *ref)
11072 {
11073         MonoClass *klass = mono_object_class (ref);
11074         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
11075 }
11076
11077 static MonoReflectionType*
11078 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
11079 {
11080         mono_error_init (error);
11081         if (!type || type->type)
11082                 return type;
11083
11084         if (is_usertype (type)) {
11085                 type = mono_reflection_type_get_underlying_system_type (type, error);
11086                 return_val_if_nok (error, NULL);
11087                 if (is_usertype (type)) {
11088                         mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
11089                         return NULL;
11090                 }
11091         }
11092
11093         return type;
11094 }
11095 /**
11096  * encode_cattr_value:
11097  * Encode a value in a custom attribute stream of bytes.
11098  * The value to encode is either supplied as an object in argument val
11099  * (valuetypes are boxed), or as a pointer to the data in the
11100  * argument argval.
11101  * @type represents the type of the value
11102  * @buffer is the start of the buffer
11103  * @p the current position in the buffer
11104  * @buflen contains the size of the buffer and is used to return the new buffer size
11105  * if this needs to be realloced.
11106  * @retbuffer and @retp return the start and the position of the buffer
11107  * @error set on error.
11108  */
11109 static void
11110 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
11111 {
11112         MonoTypeEnum simple_type;
11113         
11114         mono_error_init (error);
11115         if ((p-buffer) + 10 >= *buflen) {
11116                 char *newbuf;
11117                 *buflen *= 2;
11118                 newbuf = (char *)g_realloc (buffer, *buflen);
11119                 p = newbuf + (p-buffer);
11120                 buffer = newbuf;
11121         }
11122         if (!argval)
11123                 argval = ((char*)arg + sizeof (MonoObject));
11124         simple_type = type->type;
11125 handle_enum:
11126         switch (simple_type) {
11127         case MONO_TYPE_BOOLEAN:
11128         case MONO_TYPE_U1:
11129         case MONO_TYPE_I1:
11130                 *p++ = *argval;
11131                 break;
11132         case MONO_TYPE_CHAR:
11133         case MONO_TYPE_U2:
11134         case MONO_TYPE_I2:
11135                 swap_with_size (p, argval, 2, 1);
11136                 p += 2;
11137                 break;
11138         case MONO_TYPE_U4:
11139         case MONO_TYPE_I4:
11140         case MONO_TYPE_R4:
11141                 swap_with_size (p, argval, 4, 1);
11142                 p += 4;
11143                 break;
11144         case MONO_TYPE_R8:
11145                 swap_with_size (p, argval, 8, 1);
11146                 p += 8;
11147                 break;
11148         case MONO_TYPE_U8:
11149         case MONO_TYPE_I8:
11150                 swap_with_size (p, argval, 8, 1);
11151                 p += 8;
11152                 break;
11153         case MONO_TYPE_VALUETYPE:
11154                 if (type->data.klass->enumtype) {
11155                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
11156                         goto handle_enum;
11157                 } else {
11158                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11159                 }
11160                 break;
11161         case MONO_TYPE_STRING: {
11162                 char *str;
11163                 guint32 slen;
11164                 if (!arg) {
11165                         *p++ = 0xFF;
11166                         break;
11167                 }
11168                 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
11169                 return_if_nok (error);
11170                 slen = strlen (str);
11171                 if ((p-buffer) + 10 + slen >= *buflen) {
11172                         char *newbuf;
11173                         *buflen *= 2;
11174                         *buflen += slen;
11175                         newbuf = (char *)g_realloc (buffer, *buflen);
11176                         p = newbuf + (p-buffer);
11177                         buffer = newbuf;
11178                 }
11179                 mono_metadata_encode_value (slen, p, &p);
11180                 memcpy (p, str, slen);
11181                 p += slen;
11182                 g_free (str);
11183                 break;
11184         }
11185         case MONO_TYPE_CLASS: {
11186                 char *str;
11187                 guint32 slen;
11188                 MonoType *arg_type;
11189                 if (!arg) {
11190                         *p++ = 0xFF;
11191                         break;
11192                 }
11193 handle_type:
11194                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11195                 return_if_nok (error);
11196
11197                 str = type_get_qualified_name (arg_type, NULL);
11198                 slen = strlen (str);
11199                 if ((p-buffer) + 10 + slen >= *buflen) {
11200                         char *newbuf;
11201                         *buflen *= 2;
11202                         *buflen += slen;
11203                         newbuf = (char *)g_realloc (buffer, *buflen);
11204                         p = newbuf + (p-buffer);
11205                         buffer = newbuf;
11206                 }
11207                 mono_metadata_encode_value (slen, p, &p);
11208                 memcpy (p, str, slen);
11209                 p += slen;
11210                 g_free (str);
11211                 break;
11212         }
11213         case MONO_TYPE_SZARRAY: {
11214                 int len, i;
11215                 MonoClass *eclass, *arg_eclass;
11216
11217                 if (!arg) {
11218                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11219                         break;
11220                 }
11221                 len = mono_array_length ((MonoArray*)arg);
11222                 *p++ = len & 0xff;
11223                 *p++ = (len >> 8) & 0xff;
11224                 *p++ = (len >> 16) & 0xff;
11225                 *p++ = (len >> 24) & 0xff;
11226                 *retp = p;
11227                 *retbuffer = buffer;
11228                 eclass = type->data.klass;
11229                 arg_eclass = mono_object_class (arg)->element_class;
11230
11231                 if (!eclass) {
11232                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11233                         eclass = mono_defaults.object_class;
11234                 }
11235                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11236                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11237                         int elsize = mono_class_array_element_size (arg_eclass);
11238                         for (i = 0; i < len; ++i) {
11239                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11240                                 return_if_nok (error);
11241                                 elptr += elsize;
11242                         }
11243                 } else if (eclass->valuetype && arg_eclass->valuetype) {
11244                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11245                         int elsize = mono_class_array_element_size (eclass);
11246                         for (i = 0; i < len; ++i) {
11247                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11248                                 return_if_nok (error);
11249                                 elptr += elsize;
11250                         }
11251                 } else {
11252                         for (i = 0; i < len; ++i) {
11253                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11254                                 return_if_nok (error);
11255                         }
11256                 }
11257                 break;
11258         }
11259         case MONO_TYPE_OBJECT: {
11260                 MonoClass *klass;
11261                 char *str;
11262                 guint32 slen;
11263
11264                 /*
11265                  * The parameter type is 'object' but the type of the actual
11266                  * argument is not. So we have to add type information to the blob
11267                  * too. This is completely undocumented in the spec.
11268                  */
11269
11270                 if (arg == NULL) {
11271                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
11272                         *p++ = 0xFF;
11273                         break;
11274                 }
11275                 
11276                 klass = mono_object_class (arg);
11277
11278                 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11279                         *p++ = 0x50;
11280                         goto handle_type;
11281                 } else {
11282                         return_if_nok (error);
11283                 }
11284
11285                 if (klass->enumtype) {
11286                         *p++ = 0x55;
11287                 } else if (klass == mono_defaults.string_class) {
11288                         simple_type = MONO_TYPE_STRING;
11289                         *p++ = 0x0E;
11290                         goto handle_enum;
11291                 } else if (klass->rank == 1) {
11292                         *p++ = 0x1D;
11293                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11294                                 /* See Partition II, Appendix B3 */
11295                                 *p++ = 0x51;
11296                         else
11297                                 *p++ = klass->element_class->byval_arg.type;
11298                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11299                         return_if_nok (error);
11300                         break;
11301                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11302                         *p++ = simple_type = klass->byval_arg.type;
11303                         goto handle_enum;
11304                 } else {
11305                         g_error ("unhandled type in custom attr");
11306                 }
11307                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11308                 slen = strlen (str);
11309                 if ((p-buffer) + 10 + slen >= *buflen) {
11310                         char *newbuf;
11311                         *buflen *= 2;
11312                         *buflen += slen;
11313                         newbuf = (char *)g_realloc (buffer, *buflen);
11314                         p = newbuf + (p-buffer);
11315                         buffer = newbuf;
11316                 }
11317                 mono_metadata_encode_value (slen, p, &p);
11318                 memcpy (p, str, slen);
11319                 p += slen;
11320                 g_free (str);
11321                 simple_type = mono_class_enum_basetype (klass)->type;
11322                 goto handle_enum;
11323         }
11324         default:
11325                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11326         }
11327         *retp = p;
11328         *retbuffer = buffer;
11329 }
11330
11331 static void
11332 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11333 {
11334         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11335                 char *str = type_get_qualified_name (type, NULL);
11336                 int slen = strlen (str);
11337
11338                 *p++ = 0x55;
11339                 /*
11340                  * This seems to be optional...
11341                  * *p++ = 0x80;
11342                  */
11343                 mono_metadata_encode_value (slen, p, &p);
11344                 memcpy (p, str, slen);
11345                 p += slen;
11346                 g_free (str);
11347         } else if (type->type == MONO_TYPE_OBJECT) {
11348                 *p++ = 0x51;
11349         } else if (type->type == MONO_TYPE_CLASS) {
11350                 /* it should be a type: encode_cattr_value () has the check */
11351                 *p++ = 0x50;
11352         } else {
11353                 mono_metadata_encode_value (type->type, p, &p);
11354                 if (type->type == MONO_TYPE_SZARRAY)
11355                         /* See the examples in Partition VI, Annex B */
11356                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11357         }
11358
11359         *retp = p;
11360 }
11361
11362 #ifndef DISABLE_REFLECTION_EMIT
11363 static void
11364 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11365 {
11366         int len;
11367
11368         mono_error_init (error);
11369
11370         /* Preallocate a large enough buffer */
11371         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11372                 char *str = type_get_qualified_name (type, NULL);
11373                 len = strlen (str);
11374                 g_free (str);
11375         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11376                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11377                 len = strlen (str);
11378                 g_free (str);
11379         } else {
11380                 len = 0;
11381         }
11382         len += strlen (name);
11383
11384         if ((p-buffer) + 20 + len >= *buflen) {
11385                 char *newbuf;
11386                 *buflen *= 2;
11387                 *buflen += len;
11388                 newbuf = (char *)g_realloc (buffer, *buflen);
11389                 p = newbuf + (p-buffer);
11390                 buffer = newbuf;
11391         }
11392
11393         encode_field_or_prop_type (type, p, &p);
11394
11395         len = strlen (name);
11396         mono_metadata_encode_value (len, p, &p);
11397         memcpy (p, name, len);
11398         p += len;
11399         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11400         return_if_nok (error);
11401         *retp = p;
11402         *retbuffer = buffer;
11403 }
11404
11405 /**
11406  * mono_reflection_get_custom_attrs_blob:
11407  * @ctor: custom attribute constructor
11408  * @ctorArgs: arguments o the constructor
11409  * @properties:
11410  * @propValues:
11411  * @fields:
11412  * @fieldValues:
11413  * 
11414  * Creates the blob of data that needs to be saved in the metadata and that represents
11415  * the custom attributed described by @ctor, @ctorArgs etc.
11416  * Returns: a Byte array representing the blob of data.
11417  */
11418 MonoArray*
11419 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11420 {
11421         MonoError error;
11422         MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11423         mono_error_cleanup (&error);
11424         return result;
11425 }
11426
11427 /**
11428  * mono_reflection_get_custom_attrs_blob_checked:
11429  * @ctor: custom attribute constructor
11430  * @ctorArgs: arguments o the constructor
11431  * @properties:
11432  * @propValues:
11433  * @fields:
11434  * @fieldValues:
11435  * @error: set on error
11436  * 
11437  * Creates the blob of data that needs to be saved in the metadata and that represents
11438  * the custom attributed described by @ctor, @ctorArgs etc.
11439  * Returns: a Byte array representing the blob of data.  On failure returns NULL and sets @error.
11440  */
11441 MonoArray*
11442 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error) 
11443 {
11444         MonoArray *result = NULL;
11445         MonoMethodSignature *sig;
11446         MonoObject *arg;
11447         char *buffer, *p;
11448         guint32 buflen, i;
11449
11450         mono_error_init (error);
11451
11452         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11453                 /* sig is freed later so allocate it in the heap */
11454                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11455                 if (!is_ok (error)) {
11456                         g_free (sig);
11457                         return NULL;
11458                 }
11459         } else {
11460                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11461         }
11462
11463         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11464         buflen = 256;
11465         p = buffer = (char *)g_malloc (buflen);
11466         /* write the prolog */
11467         *p++ = 1;
11468         *p++ = 0;
11469         for (i = 0; i < sig->param_count; ++i) {
11470                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11471                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11472                 if (!is_ok (error)) goto leave;
11473         }
11474         i = 0;
11475         if (properties)
11476                 i += mono_array_length (properties);
11477         if (fields)
11478                 i += mono_array_length (fields);
11479         *p++ = i & 0xff;
11480         *p++ = (i >> 8) & 0xff;
11481         if (properties) {
11482                 MonoObject *prop;
11483                 for (i = 0; i < mono_array_length (properties); ++i) {
11484                         MonoType *ptype;
11485                         char *pname;
11486
11487                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11488                         get_prop_name_and_type (prop, &pname, &ptype, error);
11489                         if (!is_ok (error)) goto leave;
11490                         *p++ = 0x54; /* PROPERTY signature */
11491                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11492                         g_free (pname);
11493                         if (!is_ok (error)) goto leave;
11494                 }
11495         }
11496
11497         if (fields) {
11498                 MonoObject *field;
11499                 for (i = 0; i < mono_array_length (fields); ++i) {
11500                         MonoType *ftype;
11501                         char *fname;
11502
11503                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11504                         get_field_name_and_type (field, &fname, &ftype, error);
11505                         if (!is_ok (error)) goto leave;
11506                         *p++ = 0x53; /* FIELD signature */
11507                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11508                         g_free (fname);
11509                         if (!is_ok (error)) goto leave;
11510                 }
11511         }
11512
11513         g_assert (p - buffer <= buflen);
11514         buflen = p - buffer;
11515         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
11516         if (!is_ok (error))
11517                 goto leave;
11518         p = mono_array_addr (result, char, 0);
11519         memcpy (p, buffer, buflen);
11520 leave:
11521         g_free (buffer);
11522         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11523                 g_free (sig);
11524         return result;
11525 }
11526
11527 /**
11528  * reflection_setup_internal_class:
11529  * @tb: a TypeBuilder object
11530  * @error: set on error
11531  *
11532  * Creates a MonoClass that represents the TypeBuilder.
11533  * This is a trick that lets us simplify a lot of reflection code
11534  * (and will allow us to support Build and Run assemblies easier).
11535  *
11536  * Returns TRUE on success. On failure, returns FALSE and sets @error.
11537  */
11538 static gboolean
11539 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11540 {
11541         MonoClass *klass, *parent;
11542
11543         mono_error_init (error);
11544         RESOLVE_TYPE (tb->parent, error);
11545         return_val_if_nok (error, FALSE);
11546
11547         mono_loader_lock ();
11548
11549         if (tb->parent) {
11550                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11551                 if (!is_ok (error)) {
11552                         mono_loader_unlock ();
11553                         return FALSE;
11554                 }
11555                 /* check so we can compile corlib correctly */
11556                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11557                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11558                         parent = parent_type->data.klass;
11559                 } else {
11560                         parent = mono_class_from_mono_type (parent_type);
11561                 }
11562         } else {
11563                 parent = NULL;
11564         }
11565         
11566         /* the type has already being created: it means we just have to change the parent */
11567         if (tb->type.type) {
11568                 klass = mono_class_from_mono_type (tb->type.type);
11569                 klass->parent = NULL;
11570                 /* fool mono_class_setup_parent */
11571                 klass->supertypes = NULL;
11572                 mono_class_setup_parent (klass, parent);
11573                 mono_class_setup_mono_type (klass);
11574                 mono_loader_unlock ();
11575                 return TRUE;
11576         }
11577
11578         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11579
11580         klass->image = &tb->module->dynamic_image->image;
11581
11582         klass->inited = 1; /* we lie to the runtime */
11583         klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11584         if (!is_ok (error))
11585                 goto failure;
11586         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11587         if (!is_ok (error))
11588                 goto failure;
11589         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11590         klass->flags = tb->attrs;
11591         
11592         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11593
11594         klass->element_class = klass;
11595
11596         if (mono_class_get_ref_info (klass) == NULL) {
11597
11598                 mono_class_set_ref_info (klass, tb);
11599
11600                 /* Put into cache so mono_class_get_checked () will find it.
11601                 Skip nested types as those should not be available on the global scope. */
11602                 if (!tb->nesting_type)
11603                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11604
11605                 /*
11606                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11607                 by performing a mono_class_get which does the full resolution.
11608
11609                 Working around this semantics would require us to write a lot of code for no clear advantage.
11610                 */
11611                 mono_image_append_class_to_reflection_info_set (klass);
11612         } else {
11613                 g_assert (mono_class_get_ref_info (klass) == tb);
11614         }
11615
11616         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11617
11618         if (parent != NULL) {
11619                 mono_class_setup_parent (klass, parent);
11620         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11621                 const char *old_n = klass->name;
11622                 /* trick to get relative numbering right when compiling corlib */
11623                 klass->name = "BuildingObject";
11624                 mono_class_setup_parent (klass, mono_defaults.object_class);
11625                 klass->name = old_n;
11626         }
11627
11628         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11629                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11630                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11631                 klass->instance_size = sizeof (MonoObject);
11632                 klass->size_inited = 1;
11633                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11634         }
11635
11636         mono_class_setup_mono_type (klass);
11637
11638         mono_class_setup_supertypes (klass);
11639
11640         /*
11641          * FIXME: handle interfaces.
11642          */
11643
11644         tb->type.type = &klass->byval_arg;
11645
11646         if (tb->nesting_type) {
11647                 g_assert (tb->nesting_type->type);
11648                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11649                 if (!is_ok (error)) goto failure;
11650                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11651         }
11652
11653         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11654
11655         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11656         
11657         mono_loader_unlock ();
11658         return TRUE;
11659
11660 failure:
11661         mono_loader_unlock ();
11662         return FALSE;
11663 }
11664
11665 /**
11666  * mono_reflection_setup_internal_class:
11667  * @tb: a TypeBuilder object
11668  *
11669  * (icall)
11670  * Creates a MonoClass that represents the TypeBuilder.
11671  * This is a trick that lets us simplify a lot of reflection code
11672  * (and will allow us to support Build and Run assemblies easier).
11673  *
11674  */
11675 void
11676 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11677 {
11678         MonoError error;
11679         (void) reflection_setup_internal_class (tb, &error);
11680         mono_error_set_pending_exception (&error);
11681 }
11682
11683 /*
11684  * mono_reflection_setup_generic_class:
11685  * @tb: a TypeBuilder object
11686  *
11687  * Setup the generic class before adding the first generic parameter.
11688  */
11689 void
11690 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11691 {
11692 }
11693
11694 /**
11695  * mono_reflection_create_generic_class:
11696  * @tb: a TypeBuilder object
11697  * @error: set on error
11698  *
11699  * Creates the generic class after all generic parameters have been added.
11700  * On success returns TRUE, on failure returns FALSE and sets @error.
11701  * 
11702  */
11703 gboolean
11704 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11705 {
11706
11707         MonoClass *klass;
11708         int count, i;
11709
11710         mono_error_init (error);
11711
11712         klass = mono_class_from_mono_type (tb->type.type);
11713
11714         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11715
11716         if (klass->generic_container || (count == 0))
11717                 return TRUE;
11718
11719         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11720
11721         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11722
11723         klass->generic_container->owner.klass = klass;
11724         klass->generic_container->type_argc = count;
11725         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11726
11727         klass->is_generic = 1;
11728
11729         for (i = 0; i < count; i++) {
11730                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11731                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
11732                 return_val_if_nok (error, FALSE);
11733                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11734                 klass->generic_container->type_params [i] = *param;
11735                 /*Make sure we are a diferent type instance */
11736                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11737                 klass->generic_container->type_params [i].info.pklass = NULL;
11738                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11739
11740                 g_assert (klass->generic_container->type_params [i].param.owner);
11741         }
11742
11743         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11744         return TRUE;
11745 }
11746
11747 /**
11748  * reflection_create_internal_class:
11749  * @tb: a TypeBuilder object
11750  * @error: set on error
11751  *
11752  * Actually create the MonoClass that is associated with the TypeBuilder.
11753  * On success returns TRUE, on failure returns FALSE and sets @error.
11754  *
11755  */
11756 static gboolean
11757 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11758 {
11759
11760         MonoClass *klass;
11761
11762         mono_error_init (error);
11763         klass = mono_class_from_mono_type (tb->type.type);
11764
11765         mono_loader_lock ();
11766         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11767                 MonoReflectionFieldBuilder *fb;
11768                 MonoClass *ec;
11769                 MonoType *enum_basetype;
11770
11771                 g_assert (tb->fields != NULL);
11772                 g_assert (mono_array_length (tb->fields) >= 1);
11773
11774                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11775
11776                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11777                 if (!is_ok (error)) {
11778                         mono_loader_unlock ();
11779                         return FALSE;
11780                 }
11781                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11782                         mono_loader_unlock ();
11783                         return TRUE;
11784                 }
11785
11786                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11787                 if (!is_ok (error)) {
11788                         mono_loader_unlock ();
11789                         return FALSE;
11790                 }
11791                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11792                 if (!klass->element_class)
11793                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11794
11795                 /*
11796                  * get the element_class from the current corlib.
11797                  */
11798                 ec = default_class_from_mono_type (enum_basetype);
11799                 klass->instance_size = ec->instance_size;
11800                 klass->size_inited = 1;
11801                 /* 
11802                  * this is almost safe to do with enums and it's needed to be able
11803                  * to create objects of the enum type (for use in SetConstant).
11804                  */
11805                 /* FIXME: Does this mean enums can't have method overrides ? */
11806                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11807         }
11808         mono_loader_unlock ();
11809         return TRUE;
11810 }
11811
11812 /**
11813  * mono_reflection_create_internal_class:
11814  * @tb: a TypeBuilder object
11815  *
11816  * (icall)
11817  * Actually create the MonoClass that is associated with the TypeBuilder.
11818  */
11819 void
11820 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11821 {
11822         MonoError error;
11823         (void) reflection_create_internal_class (tb, &error);
11824         mono_error_set_pending_exception (&error);
11825 }
11826
11827 static MonoMarshalSpec*
11828 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11829                                 MonoReflectionMarshal *minfo, MonoError *error)
11830 {
11831         MonoMarshalSpec *res;
11832
11833         mono_error_init (error);
11834
11835         res = image_g_new0 (image, MonoMarshalSpec, 1);
11836         res->native = (MonoMarshalNative)minfo->type;
11837
11838         switch (minfo->type) {
11839         case MONO_NATIVE_LPARRAY:
11840                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11841                 if (minfo->has_size) {
11842                         res->data.array_data.param_num = minfo->param_num;
11843                         res->data.array_data.num_elem = minfo->count;
11844                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11845                 }
11846                 else {
11847                         res->data.array_data.param_num = -1;
11848                         res->data.array_data.num_elem = -1;
11849                         res->data.array_data.elem_mult = -1;
11850                 }
11851                 break;
11852
11853         case MONO_NATIVE_BYVALTSTR:
11854         case MONO_NATIVE_BYVALARRAY:
11855                 res->data.array_data.num_elem = minfo->count;
11856                 break;
11857
11858         case MONO_NATIVE_CUSTOM:
11859                 if (minfo->marshaltyperef) {
11860                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11861                         if (!is_ok (error)) {
11862                                 image_g_free (image, res);
11863                                 return NULL;
11864                         }
11865                         res->data.custom_data.custom_name =
11866                                 type_get_fully_qualified_name (marshaltyperef);
11867                 }
11868                 if (minfo->mcookie) {
11869                         res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
11870                         if (!is_ok (error)) {
11871                                 image_g_free (image, res);
11872                                 return NULL;
11873                         }
11874                 }
11875                 break;
11876
11877         default:
11878                 break;
11879         }
11880
11881         return res;
11882 }
11883 #endif /* !DISABLE_REFLECTION_EMIT */
11884
11885 MonoReflectionMarshalAsAttribute*
11886 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11887                                                         MonoMarshalSpec *spec, MonoError *error)
11888 {
11889         MonoReflectionType *rt;
11890         MonoReflectionMarshalAsAttribute *minfo;
11891         MonoType *mtype;
11892
11893         mono_error_init (error);
11894         
11895         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11896         if (!minfo)
11897                 return NULL;
11898         minfo->utype = spec->native;
11899
11900         switch (minfo->utype) {
11901         case MONO_NATIVE_LPARRAY:
11902                 minfo->array_subtype = spec->data.array_data.elem_type;
11903                 minfo->size_const = spec->data.array_data.num_elem;
11904                 if (spec->data.array_data.param_num != -1)
11905                         minfo->size_param_index = spec->data.array_data.param_num;
11906                 break;
11907
11908         case MONO_NATIVE_BYVALTSTR:
11909         case MONO_NATIVE_BYVALARRAY:
11910                 minfo->size_const = spec->data.array_data.num_elem;
11911                 break;
11912
11913         case MONO_NATIVE_CUSTOM:
11914                 if (spec->data.custom_data.custom_name) {
11915                         mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11916                         return_val_if_nok  (error, NULL);
11917
11918                         if (mtype) {
11919                                 rt = mono_type_get_object_checked (domain, mtype, error);
11920                                 if (!rt)
11921                                         return NULL;
11922
11923                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11924                         }
11925
11926                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11927                 }
11928                 if (spec->data.custom_data.cookie)
11929                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11930                 break;
11931
11932         default:
11933                 break;
11934         }
11935
11936         return minfo;
11937 }
11938
11939 #ifndef DISABLE_REFLECTION_EMIT
11940 static MonoMethod*
11941 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11942                                          ReflectionMethodBuilder *rmb,
11943                                          MonoMethodSignature *sig,
11944                                          MonoError *error)
11945 {
11946         MonoMethod *m;
11947         MonoMethodWrapper *wrapperm;
11948         MonoMarshalSpec **specs;
11949         MonoReflectionMethodAux *method_aux;
11950         MonoImage *image;
11951         gboolean dynamic;
11952         int i;
11953
11954         mono_error_init (error);
11955         /*
11956          * Methods created using a MethodBuilder should have their memory allocated
11957          * inside the image mempool, while dynamic methods should have their memory
11958          * malloc'd.
11959          */
11960         dynamic = rmb->refs != NULL;
11961         image = dynamic ? NULL : klass->image;
11962
11963         if (!dynamic)
11964                 g_assert (!klass->generic_class);
11965
11966         mono_loader_lock ();
11967
11968         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11969                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11970                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11971         else
11972                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11973
11974         wrapperm = (MonoMethodWrapper*)m;
11975
11976         m->dynamic = dynamic;
11977         m->slot = -1;
11978         m->flags = rmb->attrs;
11979         m->iflags = rmb->iattrs;
11980         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11981         m->klass = klass;
11982         m->signature = sig;
11983         m->sre_method = TRUE;
11984         m->skip_visibility = rmb->skip_visibility;
11985         if (rmb->table_idx)
11986                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11987
11988         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11989                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11990                         m->string_ctor = 1;
11991
11992                 m->signature->pinvoke = 1;
11993         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11994                 m->signature->pinvoke = 1;
11995
11996                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11997
11998                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
11999                 mono_error_assert_ok (error);
12000                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
12001                 mono_error_assert_ok (error);
12002                 
12003                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
12004
12005                 if (image_is_dynamic (klass->image))
12006                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12007
12008                 mono_loader_unlock ();
12009
12010                 return m;
12011         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
12012                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
12013                 MonoMethodHeader *header;
12014                 guint32 code_size;
12015                 gint32 max_stack, i;
12016                 gint32 num_locals = 0;
12017                 gint32 num_clauses = 0;
12018                 guint8 *code;
12019
12020                 if (rmb->ilgen) {
12021                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
12022                         code_size = rmb->ilgen->code_len;
12023                         max_stack = rmb->ilgen->max_stack;
12024                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
12025                         if (rmb->ilgen->ex_handlers)
12026                                 num_clauses = method_count_clauses (rmb->ilgen);
12027                 } else {
12028                         if (rmb->code) {
12029                                 code = mono_array_addr (rmb->code, guint8, 0);
12030                                 code_size = mono_array_length (rmb->code);
12031                                 /* we probably need to run a verifier on the code... */
12032                                 max_stack = 8; 
12033                         }
12034                         else {
12035                                 code = NULL;
12036                                 code_size = 0;
12037                                 max_stack = 8;
12038                         }
12039                 }
12040
12041                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
12042                 header->code_size = code_size;
12043                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
12044                 memcpy ((char*)header->code, code, code_size);
12045                 header->max_stack = max_stack;
12046                 header->init_locals = rmb->init_locals;
12047                 header->num_locals = num_locals;
12048
12049                 for (i = 0; i < num_locals; ++i) {
12050                         MonoReflectionLocalBuilder *lb = 
12051                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
12052
12053                         header->locals [i] = image_g_new0 (image, MonoType, 1);
12054                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
12055                         mono_error_assert_ok (error);
12056                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
12057                 }
12058
12059                 header->num_clauses = num_clauses;
12060                 if (num_clauses) {
12061                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
12062                                                                  rmb->ilgen, num_clauses, error);
12063                         mono_error_assert_ok (error);
12064                 }
12065
12066                 wrapperm->header = header;
12067         }
12068
12069         if (rmb->generic_params) {
12070                 int count = mono_array_length (rmb->generic_params);
12071                 MonoGenericContainer *container = rmb->generic_container;
12072
12073                 g_assert (container);
12074
12075                 container->type_argc = count;
12076                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
12077                 container->owner.method = m;
12078                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
12079
12080                 m->is_generic = TRUE;
12081                 mono_method_set_generic_container (m, container);
12082
12083                 for (i = 0; i < count; i++) {
12084                         MonoReflectionGenericParam *gp =
12085                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
12086                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
12087                         mono_error_assert_ok (error);
12088                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
12089                         container->type_params [i] = *param;
12090                 }
12091
12092                 /*
12093                  * The method signature might have pointers to generic parameters that belong to other methods.
12094                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
12095                  * generic parameters.
12096                  */
12097                 for (i = 0; i < m->signature->param_count; ++i) {
12098                         MonoType *t = m->signature->params [i];
12099                         if (t->type == MONO_TYPE_MVAR) {
12100                                 MonoGenericParam *gparam =  t->data.generic_param;
12101                                 if (gparam->num < count) {
12102                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
12103                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
12104                                 }
12105
12106                         }
12107                 }
12108
12109                 if (klass->generic_container) {
12110                         container->parent = klass->generic_container;
12111                         container->context.class_inst = klass->generic_container->context.class_inst;
12112                 }
12113                 container->context.method_inst = mono_get_shared_generic_inst (container);
12114         }
12115
12116         if (rmb->refs) {
12117                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
12118                 int i;
12119                 void **data;
12120
12121                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
12122
12123                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
12124                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
12125                 for (i = 0; i < rmb->nrefs; ++i)
12126                         data [i + 1] = rmb->refs [i];
12127         }
12128
12129         method_aux = NULL;
12130
12131         /* Parameter info */
12132         if (rmb->pinfo) {
12133                 if (!method_aux)
12134                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12135                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
12136                 for (i = 0; i <= m->signature->param_count; ++i) {
12137                         MonoReflectionParamBuilder *pb;
12138                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12139                                 if ((i > 0) && (pb->attrs)) {
12140                                         /* Make a copy since it might point to a shared type structure */
12141                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
12142                                         m->signature->params [i - 1]->attrs = pb->attrs;
12143                                 }
12144
12145                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
12146                                         MonoDynamicImage *assembly;
12147                                         guint32 idx, len;
12148                                         MonoTypeEnum def_type;
12149                                         char *p;
12150                                         const char *p2;
12151
12152                                         if (!method_aux->param_defaults) {
12153                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12154                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12155                                         }
12156                                         assembly = (MonoDynamicImage*)klass->image;
12157                                         idx = encode_constant (assembly, pb->def_value, &def_type);
12158                                         /* Copy the data from the blob since it might get realloc-ed */
12159                                         p = assembly->blob.data + idx;
12160                                         len = mono_metadata_decode_blob_size (p, &p2);
12161                                         len += p2 - p;
12162                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12163                                         method_aux->param_default_types [i] = def_type;
12164                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12165                                 }
12166
12167                                 if (pb->name) {
12168                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
12169                                         mono_error_assert_ok (error);
12170                                 }
12171                                 if (pb->cattrs) {
12172                                         if (!method_aux->param_cattr)
12173                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12174                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12175                                 }
12176                         }
12177                 }
12178         }
12179
12180         /* Parameter marshalling */
12181         specs = NULL;
12182         if (rmb->pinfo)         
12183                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12184                         MonoReflectionParamBuilder *pb;
12185                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12186                                 if (pb->marshal_info) {
12187                                         if (specs == NULL)
12188                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12189                                         specs [pb->position] = 
12190                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
12191                                         if (!is_ok (error)) {
12192                                                 mono_loader_unlock ();
12193                                                 image_g_free (image, specs);
12194                                                 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
12195                                                 return NULL;
12196                                         }
12197                                 }
12198                         }
12199                 }
12200         if (specs != NULL) {
12201                 if (!method_aux)
12202                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12203                 method_aux->param_marshall = specs;
12204         }
12205
12206         if (image_is_dynamic (klass->image) && method_aux)
12207                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12208
12209         mono_loader_unlock ();
12210
12211         return m;
12212 }       
12213
12214 static MonoMethod*
12215 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12216 {
12217         ReflectionMethodBuilder rmb;
12218         MonoMethodSignature *sig;
12219
12220         mono_loader_lock ();
12221         g_assert (klass->image != NULL);
12222         sig = ctor_builder_to_signature (klass->image, mb, error);
12223         mono_loader_unlock ();
12224         return_val_if_nok (error, NULL);
12225
12226         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12227                 return NULL;
12228
12229         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12230         return_val_if_nok (error, NULL);
12231         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12232
12233         /* If we are in a generic class, we might be called multiple times from inflate_method */
12234         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12235                 /* ilgen is no longer needed */
12236                 mb->ilgen = NULL;
12237         }
12238
12239         return mb->mhandle;
12240 }
12241
12242 static MonoMethod*
12243 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12244 {
12245         ReflectionMethodBuilder rmb;
12246         MonoMethodSignature *sig;
12247
12248         mono_error_init (error);
12249
12250         mono_loader_lock ();
12251         g_assert (klass->image != NULL);
12252         sig = method_builder_to_signature (klass->image, mb, error);
12253         mono_loader_unlock ();
12254         return_val_if_nok (error, NULL);
12255
12256         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12257                 return NULL;
12258
12259         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12260         return_val_if_nok (error, NULL);
12261         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12262
12263         /* If we are in a generic class, we might be called multiple times from inflate_method */
12264         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12265                 /* ilgen is no longer needed */
12266                 mb->ilgen = NULL;
12267         }
12268         return mb->mhandle;
12269 }
12270
12271 static MonoClassField*
12272 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12273 {
12274         MonoClassField *field;
12275         MonoType *custom;
12276
12277         mono_error_init (error);
12278
12279         field = g_new0 (MonoClassField, 1);
12280
12281         field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12282         mono_error_assert_ok (error);
12283         if (fb->attrs || fb->modreq || fb->modopt) {
12284                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12285                 if (!is_ok (error)) {
12286                         g_free (field);
12287                         return NULL;
12288                 }
12289                 field->type = mono_metadata_type_dup (NULL, type);
12290                 field->type->attrs = fb->attrs;
12291
12292                 g_assert (image_is_dynamic (klass->image));
12293                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12294                 g_free (field->type);
12295                 if (!is_ok (error)) {
12296                         g_free (field);
12297                         return NULL;
12298                 }
12299                 field->type = mono_metadata_type_dup (klass->image, custom);
12300                 g_free (custom);
12301         } else {
12302                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12303                 if (!is_ok (error)) {
12304                         g_free (field);
12305                         return NULL;
12306                 }
12307         }
12308         if (fb->offset != -1)
12309                 field->offset = fb->offset;
12310         field->parent = klass;
12311         mono_save_custom_attrs (klass->image, field, fb->cattrs);
12312
12313         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12314
12315         return field;
12316 }
12317 #endif
12318
12319 /**
12320  * mono_reflection_bind_generic_parameters:
12321  * @type: a managed type object (which should be some kind of generic (instance? definition?))
12322  * @type_args: the number of type arguments to bind
12323  * @types: array of type arguments
12324  * @error: set on error
12325  *
12326  * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12327  * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
12328  */
12329 MonoType*
12330 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12331 {
12332         MonoClass *klass;
12333         MonoReflectionTypeBuilder *tb = NULL;
12334         gboolean is_dynamic = FALSE;
12335         MonoClass *geninst;
12336
12337         mono_error_init (error);
12338         
12339         mono_loader_lock ();
12340
12341         if (is_sre_type_builder (mono_object_class (type))) {
12342                 tb = (MonoReflectionTypeBuilder *) type;
12343
12344                 is_dynamic = TRUE;
12345         } else if (is_sre_generic_instance (mono_object_class (type))) {
12346                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12347                 MonoReflectionType *gtd = rgi->generic_type;
12348
12349                 if (is_sre_type_builder (mono_object_class (gtd))) {
12350                         tb = (MonoReflectionTypeBuilder *)gtd;
12351                         is_dynamic = TRUE;
12352                 }
12353         }
12354
12355         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12356         if (tb && tb->generic_container) {
12357                 if (!mono_reflection_create_generic_class (tb, error)) {
12358                         mono_loader_unlock ();
12359                         return NULL;
12360                 }
12361         }
12362
12363         MonoType *t = mono_reflection_type_get_handle (type, error);
12364         if (!is_ok (error)) {
12365                 mono_loader_unlock ();
12366                 return NULL;
12367         }
12368
12369         klass = mono_class_from_mono_type (t);
12370         if (!klass->generic_container) {
12371                 mono_loader_unlock ();
12372                 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12373                 return NULL;
12374         }
12375
12376         if (klass->wastypebuilder) {
12377                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12378
12379                 is_dynamic = TRUE;
12380         }
12381
12382         mono_loader_unlock ();
12383
12384         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12385
12386         return &geninst->byval_arg;
12387 }
12388
12389 MonoClass*
12390 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12391 {
12392         MonoGenericClass *gclass;
12393         MonoGenericInst *inst;
12394
12395         g_assert (klass->generic_container);
12396
12397         inst = mono_metadata_get_generic_inst (type_argc, types);
12398         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12399
12400         return mono_generic_class_get_class (gclass);
12401 }
12402
12403 static MonoReflectionMethod*
12404 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
12405 {
12406         MonoClass *klass;
12407         MonoMethod *method, *inflated;
12408         MonoMethodInflated *imethod;
12409         MonoGenericContext tmp_context;
12410         MonoGenericInst *ginst;
12411         MonoType **type_argv;
12412         int count, i;
12413
12414         mono_error_init (error);
12415
12416         /*FIXME but this no longer should happen*/
12417         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12418 #ifndef DISABLE_REFLECTION_EMIT
12419                 MonoReflectionMethodBuilder *mb = NULL;
12420                 MonoType *tb;
12421                 MonoClass *klass;
12422
12423                 mb = (MonoReflectionMethodBuilder *) rmethod;
12424                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
12425                 return_val_if_nok (error, NULL);
12426                 klass = mono_class_from_mono_type (tb);
12427
12428                 method = methodbuilder_to_mono_method (klass, mb, error);
12429                 return_val_if_nok (error, NULL);
12430 #else
12431                 g_assert_not_reached ();
12432                 method = NULL;
12433 #endif
12434         } else {
12435                 method = rmethod->method;
12436         }
12437
12438         klass = method->klass;
12439
12440         if (method->is_inflated)
12441                 method = ((MonoMethodInflated *) method)->declaring;
12442
12443         count = mono_method_signature (method)->generic_param_count;
12444         if (count != mono_array_length (types))
12445                 return NULL;
12446
12447         type_argv = g_new0 (MonoType *, count);
12448         for (i = 0; i < count; i++) {
12449                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12450                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
12451                 if (!is_ok (error)) {
12452                         g_free (type_argv);
12453                         return NULL;
12454                 }
12455         }
12456         ginst = mono_metadata_get_generic_inst (count, type_argv);
12457         g_free (type_argv);
12458
12459         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12460         tmp_context.method_inst = ginst;
12461
12462         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
12463         mono_error_assert_ok (error);
12464         imethod = (MonoMethodInflated *) inflated;
12465
12466         /*FIXME but I think this is no longer necessary*/
12467         if (image_is_dynamic (method->klass->image)) {
12468                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12469                 /*
12470                  * This table maps metadata structures representing inflated methods/fields
12471                  * to the reflection objects representing their generic definitions.
12472                  */
12473                 mono_image_lock ((MonoImage*)image);
12474                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12475                 mono_image_unlock ((MonoImage*)image);
12476         }
12477
12478         if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
12479                 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
12480                 return NULL;
12481         }
12482         
12483         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
12484         return ret;
12485 }
12486
12487 MonoReflectionMethod*
12488 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12489 {
12490         MonoError error;
12491         MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
12492         mono_error_set_pending_exception (&error);
12493         return result;
12494 }
12495
12496
12497 #ifndef DISABLE_REFLECTION_EMIT
12498
12499 static MonoMethod *
12500 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12501 {
12502         MonoMethodInflated *imethod;
12503         MonoGenericContext *context;
12504         int i;
12505
12506         /*
12507          * With generic code sharing the klass might not be inflated.
12508          * This can happen because classes inflated with their own
12509          * type arguments are "normalized" to the uninflated class.
12510          */
12511         if (!klass->generic_class)
12512                 return method;
12513
12514         context = mono_class_get_context (klass);
12515
12516         if (klass->method.count && klass->methods) {
12517                 /* Find the already created inflated method */
12518                 for (i = 0; i < klass->method.count; ++i) {
12519                         g_assert (klass->methods [i]->is_inflated);
12520                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12521                                 break;
12522                 }
12523                 g_assert (i < klass->method.count);
12524                 imethod = (MonoMethodInflated*)klass->methods [i];
12525         } else {
12526                 MonoError error;
12527                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12528                 mono_error_assert_ok (&error);
12529         }
12530
12531         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12532                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12533
12534                 mono_image_lock ((MonoImage*)image);
12535                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12536                 mono_image_unlock ((MonoImage*)image);
12537         }
12538         return (MonoMethod *) imethod;
12539 }
12540
12541 static MonoMethod *
12542 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12543 {
12544         MonoMethod *method;
12545         MonoClass *gklass;
12546
12547         mono_error_init (error);
12548
12549         MonoClass *type_class = mono_object_class (type);
12550
12551         if (is_sre_generic_instance (type_class)) {
12552                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12553                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12554                 return_val_if_nok (error, NULL);
12555                 gklass = mono_class_from_mono_type (generic_type);
12556         } else if (is_sre_type_builder (type_class)) {
12557                 MonoType *t = mono_reflection_type_get_handle (type, error);
12558                 return_val_if_nok (error, NULL);
12559                 gklass = mono_class_from_mono_type (t);
12560         } else if (type->type) {
12561                 gklass = mono_class_from_mono_type (type->type);
12562                 gklass = mono_class_get_generic_type_definition (gklass);
12563         } else {
12564                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12565         }
12566
12567         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12568                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12569                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12570                 else {
12571                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12572                         if (!method)
12573                                 return NULL;
12574                 }
12575         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12576                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12577                 if (!method)
12578                         return NULL;
12579         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12580                 method = ((MonoReflectionMethod *) obj)->method;
12581         else {
12582                 method = NULL; /* prevent compiler warning */
12583                 g_error ("can't handle type %s", obj->vtable->klass->name);
12584         }
12585
12586         MonoType *t = mono_reflection_type_get_handle (type, error);
12587         return_val_if_nok (error, NULL);
12588         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12589 }
12590
12591 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12592 static gboolean
12593 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12594 {
12595         MonoGenericClass *gclass;
12596         MonoDynamicGenericClass *dgclass;
12597         MonoClass *klass, *gklass;
12598         MonoType *gtype;
12599         int i;
12600
12601         mono_error_init (error);
12602
12603         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12604         return_val_if_nok (error, FALSE);
12605         klass = mono_class_from_mono_type (gtype);
12606         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12607         gclass = gtype->data.generic_class;
12608
12609         if (!gclass->is_dynamic)
12610                 return TRUE;
12611
12612         dgclass = (MonoDynamicGenericClass *) gclass;
12613
12614         if (dgclass->initialized)
12615                 return TRUE;
12616
12617         gklass = gclass->container_class;
12618         mono_class_init (gklass);
12619
12620         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12621
12622         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12623         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12624         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12625
12626         for (i = 0; i < dgclass->count_fields; i++) {
12627                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12628                 MonoClassField *field, *inflated_field = NULL;
12629
12630                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12631                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12632                         return_val_if_nok (error, FALSE);
12633                 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12634                         field = ((MonoReflectionField *) obj)->field;
12635                 else {
12636                         field = NULL; /* prevent compiler warning */
12637                         g_assert_not_reached ();
12638                 }
12639
12640                 dgclass->fields [i] = *field;
12641                 dgclass->fields [i].parent = klass;
12642                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12643                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12644                 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12645                 dgclass->field_generic_types [i] = field->type;
12646                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12647                 dgclass->field_objects [i] = obj;
12648
12649                 if (inflated_field) {
12650                         g_free (inflated_field);
12651                 } else {
12652                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12653                 }
12654         }
12655
12656         dgclass->initialized = TRUE;
12657         return TRUE;
12658 }
12659
12660 void
12661 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12662 {
12663         MonoError error;
12664         (void) reflection_generic_class_initialize (type, fields, &error);
12665         mono_error_set_pending_exception (&error);
12666 }
12667
12668 void
12669 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12670 {
12671         MonoDynamicGenericClass *dgclass;
12672         int i;
12673
12674         g_assert (gclass->is_dynamic);
12675
12676         dgclass = (MonoDynamicGenericClass *)gclass;
12677
12678         for (i = 0; i < dgclass->count_fields; ++i) {
12679                 MonoClassField *field = dgclass->fields + i;
12680                 mono_metadata_free_type (field->type);
12681                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12682         }
12683 }
12684
12685 /**
12686  * fix_partial_generic_class:
12687  * @klass: a generic instantiation MonoClass
12688  * @error: set on error
12689  *
12690  * Assumes that the generic container of @klass has its vtable
12691  * initialized, and updates the parent class, insterfaces, methods and
12692  * fields of @klass by inflating the types using the generic context.
12693  *
12694  * On success returns TRUE, on failure returns FALSE and sets @error.
12695  *
12696  */
12697 static gboolean
12698 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12699 {
12700         MonoClass *gklass = klass->generic_class->container_class;
12701         MonoDynamicGenericClass *dgclass;
12702         int i;
12703
12704         mono_error_init (error);
12705
12706         if (klass->wastypebuilder)
12707                 return TRUE;
12708
12709         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12710         if (klass->parent != gklass->parent) {
12711                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12712                 if (mono_error_ok (error)) {
12713                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12714                         mono_metadata_free_type (parent_type);
12715                         if (parent != klass->parent) {
12716                                 /*fool mono_class_setup_parent*/
12717                                 klass->supertypes = NULL;
12718                                 mono_class_setup_parent (klass, parent);
12719                         }
12720                 } else {
12721                         if (gklass->wastypebuilder)
12722                                 klass->wastypebuilder = TRUE;
12723                         return FALSE;
12724                 }
12725         }
12726
12727         if (!dgclass->initialized)
12728                 return TRUE;
12729
12730         if (klass->method.count != gklass->method.count) {
12731                 klass->method.count = gklass->method.count;
12732                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12733
12734                 for (i = 0; i < klass->method.count; i++) {
12735                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12736                                 gklass->methods [i], klass, mono_class_get_context (klass), error);
12737                         mono_error_assert_ok (error);
12738                 }
12739         }
12740
12741         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12742                 klass->interface_count = gklass->interface_count;
12743                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12744                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12745
12746                 for (i = 0; i < gklass->interface_count; ++i) {
12747                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12748                         return_val_if_nok (error, FALSE);
12749
12750                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12751                         mono_metadata_free_type (iface_type);
12752
12753                         if (!ensure_runtime_vtable (klass->interfaces [i], error))
12754                                 return FALSE;
12755                 }
12756                 klass->interfaces_inited = 1;
12757         }
12758
12759         if (klass->field.count != gklass->field.count) {
12760                 klass->field.count = gklass->field.count;
12761                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12762
12763                 for (i = 0; i < klass->field.count; i++) {
12764                         klass->fields [i] = gklass->fields [i];
12765                         klass->fields [i].parent = klass;
12766                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12767                         return_val_if_nok (error, FALSE);
12768                 }
12769         }
12770
12771         /*We can only finish with this klass once it's parent has as well*/
12772         if (gklass->wastypebuilder)
12773                 klass->wastypebuilder = TRUE;
12774         return TRUE;
12775 }
12776
12777 /**
12778  * ensure_generic_class_runtime_vtable:
12779  * @klass a generic class
12780  * @error set on error
12781  *
12782  * Ensures that the generic container of @klass has a vtable and
12783  * returns TRUE on success.  On error returns FALSE and sets @error.
12784  */
12785 static gboolean
12786 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12787 {
12788         MonoClass *gklass = klass->generic_class->container_class;
12789
12790         mono_error_init (error);
12791
12792         if (!ensure_runtime_vtable (gklass, error))
12793                 return FALSE;
12794
12795         return fix_partial_generic_class (klass, error);
12796 }
12797
12798 /**
12799  * ensure_runtime_vtable:
12800  * @klass the class
12801  * @error set on error
12802  *
12803  * Ensures that @klass has a vtable and returns TRUE on success. On
12804  * error returns FALSE and sets @error.
12805  */
12806 static gboolean
12807 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12808 {
12809         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12810         int i, num, j;
12811
12812         mono_error_init (error);
12813
12814         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12815                 return TRUE;
12816         if (klass->parent)
12817                 if (!ensure_runtime_vtable (klass->parent, error))
12818                         return FALSE;
12819
12820         if (tb) {
12821                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12822                 num += tb->num_methods;
12823                 klass->method.count = num;
12824                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12825                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12826                 for (i = 0; i < num; ++i) {
12827                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12828                         if (!ctor)
12829                                 return FALSE;
12830                         klass->methods [i] = ctor;
12831                 }
12832                 num = tb->num_methods;
12833                 j = i;
12834                 for (i = 0; i < num; ++i) {
12835                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12836                         if (!meth)
12837                                 return FALSE;
12838                         klass->methods [j++] = meth;
12839                 }
12840         
12841                 if (tb->interfaces) {
12842                         klass->interface_count = mono_array_length (tb->interfaces);
12843                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12844                         for (i = 0; i < klass->interface_count; ++i) {
12845                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12846                                 return_val_if_nok (error, FALSE);
12847                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12848                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12849                                         return FALSE;
12850                         }
12851                         klass->interfaces_inited = 1;
12852                 }
12853         } else if (klass->generic_class){
12854                 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12855                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12856                         return FALSE;
12857                 }
12858         }
12859
12860         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12861                 int slot_num = 0;
12862                 for (i = 0; i < klass->method.count; ++i) {
12863                         MonoMethod *im = klass->methods [i];
12864                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12865                                 im->slot = slot_num++;
12866                 }
12867                 
12868                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12869                 mono_class_setup_interface_offsets (klass);
12870                 mono_class_setup_interface_id (klass);
12871         }
12872
12873         /*
12874          * The generic vtable is needed even if image->run is not set since some
12875          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12876          * method->slot being defined.
12877          */
12878
12879         /* 
12880          * tb->methods could not be freed since it is used for determining 
12881          * overrides during dynamic vtable construction.
12882          */
12883
12884         return TRUE;
12885 }
12886
12887 static MonoMethod*
12888 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12889 {
12890         mono_error_init (error);
12891         MonoClass *klass = mono_object_class (method);
12892         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12893                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12894                 return sr_method->method;
12895         }
12896         if (is_sre_method_builder (klass)) {
12897                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12898                 return mb->mhandle;
12899         }
12900         if (is_sre_method_on_tb_inst (klass)) {
12901                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12902                 MonoMethod *result;
12903                 /*FIXME move this to a proper method and unify with resolve_object*/
12904                 if (m->method_args) {
12905                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12906                 } else {
12907                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12908                         return_val_if_nok (error, NULL);
12909                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12910                         MonoMethod *mono_method;
12911
12912                         if (is_sre_method_builder (mono_object_class (m->mb)))
12913                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12914                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12915                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12916                         else
12917                                 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)));
12918
12919                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12920                 }
12921                 return result;
12922         }
12923
12924         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12925         return NULL;
12926 }
12927
12928 void
12929 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12930 {
12931         MonoReflectionTypeBuilder *tb;
12932         int i, j, onum;
12933         MonoReflectionMethod *m;
12934
12935         mono_error_init (error);
12936         *overrides = NULL;
12937         *num_overrides = 0;
12938
12939         g_assert (image_is_dynamic (klass->image));
12940
12941         if (!mono_class_get_ref_info (klass))
12942                 return;
12943
12944         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12945
12946         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12947
12948         onum = 0;
12949         if (tb->methods) {
12950                 for (i = 0; i < tb->num_methods; ++i) {
12951                         MonoReflectionMethodBuilder *mb = 
12952                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12953                         if (mb->override_methods)
12954                                 onum += mono_array_length (mb->override_methods);
12955                 }
12956         }
12957
12958         if (onum) {
12959                 *overrides = g_new0 (MonoMethod*, onum * 2);
12960
12961                 onum = 0;
12962                 for (i = 0; i < tb->num_methods; ++i) {
12963                         MonoReflectionMethodBuilder *mb = 
12964                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12965                         if (mb->override_methods) {
12966                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12967                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12968
12969                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12970                                         return_if_nok (error);
12971                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12972
12973                                         g_assert (mb->mhandle);
12974
12975                                         onum ++;
12976                                 }
12977                         }
12978                 }
12979         }
12980
12981         *num_overrides = onum;
12982 }
12983
12984 static void
12985 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12986 {
12987         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12988         MonoReflectionFieldBuilder *fb;
12989         MonoClassField *field;
12990         MonoImage *image = klass->image;
12991         const char *p, *p2;
12992         int i;
12993         guint32 len, idx, real_size = 0;
12994
12995         klass->field.count = tb->num_fields;
12996         klass->field.first = 0;
12997
12998         mono_error_init (error);
12999
13000         if (tb->class_size) {
13001                 if ((tb->packing_size & 0xffffff00) != 0) {
13002                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
13003                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
13004                         return;
13005                 }
13006                 klass->packing_size = tb->packing_size;
13007                 real_size = klass->instance_size + tb->class_size;
13008         }
13009
13010         if (!klass->field.count) {
13011                 klass->instance_size = MAX (klass->instance_size, real_size);
13012                 return;
13013         }
13014         
13015         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
13016         mono_class_alloc_ext (klass);
13017         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
13018         /*
13019         This is, guess what, a hack.
13020         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
13021         On the static path no field class is resolved, only types are built. This is the right thing to do
13022         but we suck.
13023         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
13024         */
13025         klass->size_inited = 1;
13026
13027         for (i = 0; i < klass->field.count; ++i) {
13028                 MonoArray *rva_data;
13029                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13030                 field = &klass->fields [i];
13031                 field->name = mono_string_to_utf8_image (image, fb->name, error);
13032                 if (!mono_error_ok (error))
13033                         return;
13034                 if (fb->attrs) {
13035                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
13036                         return_if_nok (error);
13037                         field->type = mono_metadata_type_dup (klass->image, type);
13038                         field->type->attrs = fb->attrs;
13039                 } else {
13040                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
13041                         return_if_nok (error);
13042                 }
13043
13044                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
13045                         char *base = mono_array_addr (rva_data, char, 0);
13046                         size_t size = mono_array_length (rva_data);
13047                         char *data = (char *)mono_image_alloc (klass->image, size);
13048                         memcpy (data, base, size);
13049                         klass->ext->field_def_values [i].data = data;
13050                 }
13051                 if (fb->offset != -1)
13052                         field->offset = fb->offset;
13053                 field->parent = klass;
13054                 fb->handle = field;
13055                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
13056
13057                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
13058                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
13059                 }
13060                 if (fb->def_value) {
13061                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13062                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
13063                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
13064                         /* Copy the data from the blob since it might get realloc-ed */
13065                         p = assembly->blob.data + idx;
13066                         len = mono_metadata_decode_blob_size (p, &p2);
13067                         len += p2 - p;
13068                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
13069                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
13070                 }
13071         }
13072
13073         klass->instance_size = MAX (klass->instance_size, real_size);
13074         mono_class_layout_fields (klass, klass->instance_size);
13075 }
13076
13077 static void
13078 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
13079 {
13080         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13081         MonoReflectionPropertyBuilder *pb;
13082         MonoImage *image = klass->image;
13083         MonoProperty *properties;
13084         int i;
13085
13086         mono_error_init (error);
13087
13088         if (!klass->ext)
13089                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13090
13091         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
13092         klass->ext->property.first = 0;
13093
13094         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
13095         klass->ext->properties = properties;
13096         for (i = 0; i < klass->ext->property.count; ++i) {
13097                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
13098                 properties [i].parent = klass;
13099                 properties [i].attrs = pb->attrs;
13100                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
13101                 if (!mono_error_ok (error))
13102                         return;
13103                 if (pb->get_method)
13104                         properties [i].get = pb->get_method->mhandle;
13105                 if (pb->set_method)
13106                         properties [i].set = pb->set_method->mhandle;
13107
13108                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
13109                 if (pb->def_value) {
13110                         guint32 len, idx;
13111                         const char *p, *p2;
13112                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13113                         if (!klass->ext->prop_def_values)
13114                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
13115                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
13116                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
13117                         /* Copy the data from the blob since it might get realloc-ed */
13118                         p = assembly->blob.data + idx;
13119                         len = mono_metadata_decode_blob_size (p, &p2);
13120                         len += p2 - p;
13121                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
13122                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
13123                 }
13124         }
13125 }
13126
13127 static MonoReflectionEvent *
13128 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
13129 {
13130         mono_error_init (error);
13131
13132         MonoEvent *event = g_new0 (MonoEvent, 1);
13133         MonoClass *klass;
13134
13135         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13136         if (!is_ok (error)) {
13137                 g_free (event);
13138                 return NULL;
13139         }
13140         klass = mono_class_from_mono_type (type);
13141
13142         event->parent = klass;
13143         event->attrs = eb->attrs;
13144         event->name = mono_string_to_utf8_checked (eb->name, error);
13145         if (!is_ok (error)) {
13146                 g_free (event);
13147                 return NULL;
13148         }
13149         if (eb->add_method)
13150                 event->add = eb->add_method->mhandle;
13151         if (eb->remove_method)
13152                 event->remove = eb->remove_method->mhandle;
13153         if (eb->raise_method)
13154                 event->raise = eb->raise_method->mhandle;
13155
13156 #ifndef MONO_SMALL_CONFIG
13157         if (eb->other_methods) {
13158                 int j;
13159                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
13160                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13161                         MonoReflectionMethodBuilder *mb = 
13162                                 mono_array_get (eb->other_methods,
13163                                                 MonoReflectionMethodBuilder*, j);
13164                         event->other [j] = mb->mhandle;
13165                 }
13166         }
13167 #endif
13168
13169         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
13170         if (!is_ok (error)) {
13171 #ifndef MONO_SMALL_CONFIG
13172                 g_free (event->other);
13173 #endif
13174                 g_free (event);
13175                 return NULL;
13176         }
13177         return ev_obj;
13178 }
13179
13180 MonoReflectionEvent *
13181 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13182 {
13183         MonoError error;
13184         MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13185         mono_error_set_pending_exception (&error);
13186         return result;
13187 }
13188
13189 static void
13190 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13191 {
13192         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13193         MonoReflectionEventBuilder *eb;
13194         MonoImage *image = klass->image;
13195         MonoEvent *events;
13196         int i;
13197
13198         mono_error_init (error);
13199
13200         if (!klass->ext)
13201                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13202
13203         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13204         klass->ext->event.first = 0;
13205
13206         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13207         klass->ext->events = events;
13208         for (i = 0; i < klass->ext->event.count; ++i) {
13209                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13210                 events [i].parent = klass;
13211                 events [i].attrs = eb->attrs;
13212                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13213                 if (!mono_error_ok (error))
13214                         return;
13215                 if (eb->add_method)
13216                         events [i].add = eb->add_method->mhandle;
13217                 if (eb->remove_method)
13218                         events [i].remove = eb->remove_method->mhandle;
13219                 if (eb->raise_method)
13220                         events [i].raise = eb->raise_method->mhandle;
13221
13222 #ifndef MONO_SMALL_CONFIG
13223                 if (eb->other_methods) {
13224                         int j;
13225                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13226                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13227                                 MonoReflectionMethodBuilder *mb = 
13228                                         mono_array_get (eb->other_methods,
13229                                                                         MonoReflectionMethodBuilder*, j);
13230                                 events [i].other [j] = mb->mhandle;
13231                         }
13232                 }
13233 #endif
13234                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13235         }
13236 }
13237
13238 struct remove_instantiations_user_data
13239 {
13240         MonoClass *klass;
13241         MonoError *error;
13242 };
13243
13244 static gboolean
13245 remove_instantiations_of_and_ensure_contents (gpointer key,
13246                                                   gpointer value,
13247                                                   gpointer user_data)
13248 {
13249         struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13250         MonoType *type = (MonoType*)key;
13251         MonoClass *klass = data->klass;
13252         gboolean already_failed = !is_ok (data->error);
13253         MonoError lerror;
13254         MonoError *error = already_failed ? &lerror : data->error;
13255
13256         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13257                 MonoClass *inst_klass = mono_class_from_mono_type (type);
13258                 //Ensure it's safe to use it.
13259                 if (!fix_partial_generic_class (inst_klass, error)) {
13260                         mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13261                         // Marked the class with failure, but since some other instantiation already failed,
13262                         // just report that one, and swallow the error from this one.
13263                         if (already_failed)
13264                                 mono_error_cleanup (error);
13265                 }
13266                 return TRUE;
13267         } else
13268                 return FALSE;
13269 }
13270
13271 static void
13272 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13273 {
13274         mono_error_init (error);
13275         int i;
13276
13277         if (!arr)
13278                 return;
13279
13280         for (i = 0; i < mono_array_length (arr); ++i) {
13281                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13282                 if (!mono_error_ok (error))
13283                         break;
13284         }
13285 }
13286
13287 MonoReflectionType*
13288 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13289 {
13290         MonoError error;
13291         MonoClass *klass;
13292         MonoDomain* domain;
13293         MonoReflectionType* res;
13294         int i, j;
13295
13296         mono_error_init (&error);
13297
13298         domain = mono_object_domain (tb);
13299         klass = mono_class_from_mono_type (tb->type.type);
13300
13301         /*
13302          * Check for user defined Type subclasses.
13303          */
13304         RESOLVE_TYPE (tb->parent, &error);
13305         if (!is_ok (&error))
13306                 goto failure_unlocked;
13307         check_array_for_usertypes (tb->interfaces, &error);
13308         if (!is_ok (&error))
13309                 goto failure_unlocked;
13310         if (tb->fields) {
13311                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13312                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13313                         if (fb) {
13314                                 RESOLVE_TYPE (fb->type, &error);
13315                                 if (!is_ok (&error))
13316                                         goto failure_unlocked;
13317                                 check_array_for_usertypes (fb->modreq, &error);
13318                                 if (!is_ok (&error))
13319                                         goto failure_unlocked;
13320                                 check_array_for_usertypes (fb->modopt, &error);
13321                                 if (!is_ok (&error))
13322                                         goto failure_unlocked;
13323                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13324                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13325                                         if (!is_ok (&error))
13326                                                 goto failure_unlocked;
13327                                 }
13328                         }
13329                 }
13330         }
13331         if (tb->methods) {
13332                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13333                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13334                         if (mb) {
13335                                 RESOLVE_TYPE (mb->rtype, &error);
13336                                 if (!is_ok (&error))
13337                                         goto failure_unlocked;
13338                                 check_array_for_usertypes (mb->return_modreq, &error);
13339                                 if (!is_ok (&error))
13340                                         goto failure_unlocked;
13341                                 check_array_for_usertypes (mb->return_modopt, &error);
13342                                 if (!is_ok (&error))
13343                                         goto failure_unlocked;
13344                                 check_array_for_usertypes (mb->parameters, &error);
13345                                 if (!is_ok (&error))
13346                                         goto failure_unlocked;
13347                                 if (mb->param_modreq)
13348                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13349                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13350                                                 if (!is_ok (&error))
13351                                                         goto failure_unlocked;
13352                                         }
13353                                 if (mb->param_modopt)
13354                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13355                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13356                                                 if (!is_ok (&error))
13357                                                         goto failure_unlocked;
13358                                         }
13359                         }
13360                 }
13361         }
13362         if (tb->ctors) {
13363                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13364                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13365                         if (mb) {
13366                                 check_array_for_usertypes (mb->parameters, &error);
13367                                 if (!is_ok (&error))
13368                                         goto failure_unlocked;
13369                                 if (mb->param_modreq)
13370                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13371                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13372                                                 if (!is_ok (&error))
13373                                                         goto failure_unlocked;
13374                                         }
13375                                 if (mb->param_modopt)
13376                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13377                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13378                                                 if (!is_ok (&error))
13379                                                         goto failure_unlocked;
13380                                         }
13381                         }
13382                 }
13383         }
13384
13385         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13386
13387         /* 
13388          * we need to lock the domain because the lock will be taken inside
13389          * So, we need to keep the locking order correct.
13390          */
13391         mono_loader_lock ();
13392         mono_domain_lock (domain);
13393         if (klass->wastypebuilder) {
13394                 mono_domain_unlock (domain);
13395                 mono_loader_unlock ();
13396
13397                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13398                 mono_error_set_pending_exception (&error);
13399
13400                 return res;
13401         }
13402         /*
13403          * Fields to set in klass:
13404          * the various flags: delegate/unicode/contextbound etc.
13405          */
13406         klass->flags = tb->attrs;
13407         klass->has_cctor = 1;
13408
13409         mono_class_setup_parent (klass, klass->parent);
13410         /* fool mono_class_setup_supertypes */
13411         klass->supertypes = NULL;
13412         mono_class_setup_supertypes (klass);
13413         mono_class_setup_mono_type (klass);
13414
13415 #if 0
13416         if (!((MonoDynamicImage*)klass->image)->run) {
13417                 if (klass->generic_container) {
13418                         /* FIXME: The code below can't handle generic classes */
13419                         klass->wastypebuilder = TRUE;
13420                         mono_loader_unlock ();
13421                         mono_domain_unlock (domain);
13422
13423                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13424                         mono_error_set_pending_exception (&error);
13425
13426                         return res;
13427                 }
13428         }
13429 #endif
13430
13431         /* enums are done right away */
13432         if (!klass->enumtype)
13433                 if (!ensure_runtime_vtable (klass, &error))
13434                         goto failure;
13435
13436         if (tb->subtypes) {
13437                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13438                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13439                         mono_class_alloc_ext (klass);
13440                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13441                         if (!is_ok (&error)) goto failure;
13442                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13443                 }
13444         }
13445
13446         klass->nested_classes_inited = TRUE;
13447
13448         /* fields and object layout */
13449         if (klass->parent) {
13450                 if (!klass->parent->size_inited)
13451                         mono_class_init (klass->parent);
13452                 klass->instance_size = klass->parent->instance_size;
13453                 klass->sizes.class_size = 0;
13454                 klass->min_align = klass->parent->min_align;
13455                 /* if the type has no fields we won't call the field_setup
13456                  * routine which sets up klass->has_references.
13457                  */
13458                 klass->has_references |= klass->parent->has_references;
13459         } else {
13460                 klass->instance_size = sizeof (MonoObject);
13461                 klass->min_align = 1;
13462         }
13463
13464         /* FIXME: handle packing_size and instance_size */
13465         typebuilder_setup_fields (klass, &error);
13466         if (!mono_error_ok (&error))
13467                 goto failure;
13468         typebuilder_setup_properties (klass, &error);
13469         if (!mono_error_ok (&error))
13470                 goto failure;
13471
13472         typebuilder_setup_events (klass, &error);
13473         if (!mono_error_ok (&error))
13474                 goto failure;
13475
13476         klass->wastypebuilder = TRUE;
13477
13478         /* 
13479          * If we are a generic TypeBuilder, there might be instantiations in the type cache
13480          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
13481          * we want to return normal System.MonoType objects, so clear these out from the cache.
13482          *
13483          * Together with this we must ensure the contents of all instances to match the created type.
13484          */
13485         if (domain->type_hash && klass->generic_container) {
13486                 struct remove_instantiations_user_data data;
13487                 data.klass = klass;
13488                 data.error = &error;
13489                 mono_error_assert_ok (&error);
13490                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13491                 if (!is_ok (&error))
13492                         goto failure;
13493         }
13494
13495         mono_domain_unlock (domain);
13496         mono_loader_unlock ();
13497
13498         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13499                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13500                 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13501                 goto failure_unlocked;
13502         }
13503
13504         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13505         if (!is_ok (&error))
13506                 goto failure_unlocked;
13507
13508         g_assert (res != (MonoReflectionType*)tb);
13509
13510         return res;
13511
13512 failure:
13513         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13514         klass->wastypebuilder = TRUE;
13515         mono_domain_unlock (domain);
13516         mono_loader_unlock ();
13517 failure_unlocked:
13518         mono_error_set_pending_exception (&error);
13519         return NULL;
13520 }
13521
13522 static gboolean
13523 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13524 {
13525         MonoGenericParamFull *param;
13526         MonoImage *image;
13527         MonoClass *pklass;
13528
13529         mono_error_init (error);
13530
13531         image = &gparam->tbuilder->module->dynamic_image->image;
13532
13533         param = mono_image_new0 (image, MonoGenericParamFull, 1);
13534
13535         param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13536         mono_error_assert_ok (error);
13537         param->param.num = gparam->index;
13538
13539         if (gparam->mbuilder) {
13540                 if (!gparam->mbuilder->generic_container) {
13541                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13542                         return_val_if_nok (error, FALSE);
13543
13544                         MonoClass *klass = mono_class_from_mono_type (tb);
13545                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13546                         gparam->mbuilder->generic_container->is_method = TRUE;
13547                         /* 
13548                          * Cannot set owner.method, since the MonoMethod is not created yet.
13549                          * Set the image field instead, so type_in_image () works.
13550                          */
13551                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
13552                         gparam->mbuilder->generic_container->owner.image = klass->image;
13553                 }
13554                 param->param.owner = gparam->mbuilder->generic_container;
13555         } else if (gparam->tbuilder) {
13556                 if (!gparam->tbuilder->generic_container) {
13557                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13558                         return_val_if_nok (error, FALSE);
13559                         MonoClass *klass = mono_class_from_mono_type (tb);
13560                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13561                         gparam->tbuilder->generic_container->owner.klass = klass;
13562                 }
13563                 param->param.owner = gparam->tbuilder->generic_container;
13564         }
13565
13566         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13567
13568         gparam->type.type = &pklass->byval_arg;
13569
13570         mono_class_set_ref_info (pklass, gparam);
13571         mono_image_append_class_to_reflection_info_set (pklass);
13572
13573         return TRUE;
13574 }
13575
13576 void
13577 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13578 {
13579         MonoError error;
13580         (void) reflection_initialize_generic_parameter (gparam, &error);
13581         mono_error_set_pending_exception (&error);
13582 }
13583
13584
13585 static MonoArray *
13586 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
13587 {
13588         MonoReflectionModuleBuilder *module = sig->module;
13589         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13590         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13591         guint32 buflen, i;
13592         MonoArray *result;
13593         SigBuffer buf;
13594
13595         mono_error_init (error);
13596
13597         check_array_for_usertypes (sig->arguments, error);
13598         return_val_if_nok (error, NULL);
13599
13600         sigbuffer_init (&buf, 32);
13601
13602         sigbuffer_add_value (&buf, 0x07);
13603         sigbuffer_add_value (&buf, na);
13604         if (assembly != NULL){
13605                 for (i = 0; i < na; ++i) {
13606                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13607                         encode_reflection_type (assembly, type, &buf, error);
13608                         if (!is_ok (error)) goto fail;
13609                 }
13610         }
13611
13612         buflen = buf.p - buf.buf;
13613         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13614         if (!is_ok (error)) goto fail;
13615         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13616         sigbuffer_free (&buf);
13617         return result;
13618 fail:
13619         sigbuffer_free (&buf);
13620         return NULL;
13621 }
13622
13623 MonoArray *
13624 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13625 {
13626         MonoError error;
13627         MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
13628         mono_error_set_pending_exception (&error);
13629         return result;
13630 }
13631
13632 static MonoArray *
13633 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
13634 {
13635         MonoDynamicImage *assembly = sig->module->dynamic_image;
13636         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13637         guint32 buflen, i;
13638         MonoArray *result;
13639         SigBuffer buf;
13640
13641         mono_error_init (error);
13642
13643         check_array_for_usertypes (sig->arguments, error);
13644         return_val_if_nok (error, NULL);
13645
13646         sigbuffer_init (&buf, 32);
13647
13648         sigbuffer_add_value (&buf, 0x06);
13649         for (i = 0; i < na; ++i) {
13650                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13651                 encode_reflection_type (assembly, type, &buf, error);
13652                 if (!is_ok (error))
13653                         goto fail;
13654         }
13655
13656         buflen = buf.p - buf.buf;
13657         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13658         if (!is_ok (error)) goto fail;
13659         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13660         sigbuffer_free (&buf);
13661
13662         return result;
13663 fail:
13664         sigbuffer_free (&buf);
13665         return NULL;
13666 }
13667
13668 MonoArray *
13669 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13670 {
13671         MonoError error;
13672         MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
13673         mono_error_set_pending_exception (&error);
13674         return result;
13675 }
13676
13677 typedef struct {
13678         MonoMethod *handle;
13679         MonoDomain *domain;
13680 } DynamicMethodReleaseData;
13681
13682 /*
13683  * The runtime automatically clean up those after finalization.
13684 */      
13685 static MonoReferenceQueue *dynamic_method_queue;
13686
13687 static void
13688 free_dynamic_method (void *dynamic_method)
13689 {
13690         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13691         MonoDomain *domain = data->domain;
13692         MonoMethod *method = data->handle;
13693         guint32 dis_link;
13694
13695         mono_domain_lock (domain);
13696         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13697         g_hash_table_remove (domain->method_to_dyn_method, method);
13698         mono_domain_unlock (domain);
13699         g_assert (dis_link);
13700         mono_gchandle_free (dis_link);
13701
13702         mono_runtime_free_method (domain, method);
13703         g_free (data);
13704 }
13705
13706 static gboolean
13707 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13708 {
13709         MonoReferenceQueue *queue;
13710         MonoMethod *handle;
13711         DynamicMethodReleaseData *release_data;
13712         ReflectionMethodBuilder rmb;
13713         MonoMethodSignature *sig;
13714         MonoClass *klass;
13715         MonoDomain *domain;
13716         GSList *l;
13717         int i;
13718
13719         mono_error_init (error);
13720
13721         if (mono_runtime_is_shutting_down ()) {
13722                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13723                 return FALSE;
13724         }
13725
13726         if (!(queue = dynamic_method_queue)) {
13727                 mono_loader_lock ();
13728                 if (!(queue = dynamic_method_queue))
13729                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13730                 mono_loader_unlock ();
13731         }
13732
13733         sig = dynamic_method_to_signature (mb, error);
13734         return_val_if_nok (error, FALSE);
13735
13736         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13737
13738         /*
13739          * Resolve references.
13740          */
13741         /* 
13742          * Every second entry in the refs array is reserved for storing handle_class,
13743          * which is needed by the ldtoken implementation in the JIT.
13744          */
13745         rmb.nrefs = mb->nrefs;
13746         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13747         for (i = 0; i < mb->nrefs; i += 2) {
13748                 MonoClass *handle_class;
13749                 gpointer ref;
13750                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13751
13752                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13753                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13754                         /*
13755                          * The referenced DynamicMethod should already be created by the managed
13756                          * code, except in the case of circular references. In that case, we store
13757                          * method in the refs array, and fix it up later when the referenced 
13758                          * DynamicMethod is created.
13759                          */
13760                         if (method->mhandle) {
13761                                 ref = method->mhandle;
13762                         } else {
13763                                 /* FIXME: GC object stored in unmanaged memory */
13764                                 ref = method;
13765
13766                                 /* FIXME: GC object stored in unmanaged memory */
13767                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13768                         }
13769                         handle_class = mono_defaults.methodhandle_class;
13770                 } else {
13771                         MonoException *ex = NULL;
13772                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13773                         if (!is_ok  (error)) {
13774                                 g_free (rmb.refs);
13775                                 return FALSE;
13776                         }
13777                         if (!ref)
13778                                 ex = mono_get_exception_type_load (NULL, NULL);
13779                         else if (mono_security_core_clr_enabled ())
13780                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13781
13782                         if (ex) {
13783                                 g_free (rmb.refs);
13784                                 mono_error_set_exception_instance (error, ex);
13785                                 return FALSE;
13786                         }
13787                 }
13788
13789                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13790                 rmb.refs [i + 1] = handle_class;
13791         }               
13792
13793         if (mb->owner) {
13794                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13795                 if (!is_ok (error)) {
13796                         g_free (rmb.refs);
13797                         return FALSE;
13798                 }
13799                 klass = mono_class_from_mono_type (owner_type);
13800         } else {
13801                 klass = mono_defaults.object_class;
13802         }
13803
13804         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
13805         g_free (rmb.refs);
13806         return_val_if_nok (error, FALSE);
13807
13808         release_data = g_new (DynamicMethodReleaseData, 1);
13809         release_data->handle = handle;
13810         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13811         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13812                 g_free (release_data);
13813
13814         /* Fix up refs entries pointing at us */
13815         for (l = mb->referenced_by; l; l = l->next) {
13816                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13817                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13818                 gpointer *data;
13819                 
13820                 g_assert (method->mhandle);
13821
13822                 data = (gpointer*)wrapper->method_data;
13823                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13824                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13825                                 data [i + 1] = mb->mhandle;
13826                 }
13827         }
13828         g_slist_free (mb->referenced_by);
13829
13830         /* ilgen is no longer needed */
13831         mb->ilgen = NULL;
13832
13833         domain = mono_domain_get ();
13834         mono_domain_lock (domain);
13835         if (!domain->method_to_dyn_method)
13836                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13837         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13838         mono_domain_unlock (domain);
13839
13840         return TRUE;
13841 }
13842
13843 void
13844 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13845 {
13846         MonoError error;
13847         (void) reflection_create_dynamic_method (mb, &error);
13848         mono_error_set_pending_exception (&error);
13849 }
13850
13851 #endif /* DISABLE_REFLECTION_EMIT */
13852
13853 /**
13854  * 
13855  * mono_reflection_is_valid_dynamic_token:
13856  * 
13857  * Returns TRUE if token is valid.
13858  * 
13859  */
13860 gboolean
13861 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13862 {
13863         return lookup_dyn_token (image, token) != NULL;
13864 }
13865
13866 MonoMethodSignature *
13867 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13868 {
13869         MonoMethodSignature *sig;
13870         g_assert (image_is_dynamic (image));
13871
13872         mono_error_init (error);
13873
13874         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13875         if (sig)
13876                 return sig;
13877
13878         return mono_method_signature_checked (method, error);
13879 }
13880
13881 #ifndef DISABLE_REFLECTION_EMIT
13882
13883 /**
13884  * mono_reflection_lookup_dynamic_token:
13885  *
13886  * Finish the Builder object pointed to by TOKEN and return the corresponding
13887  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13888  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13889  * mapping table.
13890  *
13891  * LOCKING: Take the loader lock
13892  */
13893 gpointer
13894 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13895 {
13896         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13897         MonoObject *obj;
13898         MonoClass *klass;
13899
13900         mono_error_init (error);
13901         
13902         obj = lookup_dyn_token (assembly, token);
13903         if (!obj) {
13904                 if (valid_token)
13905                         g_error ("Could not find required dynamic token 0x%08x", token);
13906                 else {
13907                         mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13908                         return NULL;
13909                 }
13910         }
13911
13912         if (!handle_class)
13913                 handle_class = &klass;
13914         gpointer result = resolve_object (image, obj, handle_class, context, error);
13915         return result;
13916 }
13917
13918 /*
13919  * ensure_complete_type:
13920  *
13921  *   Ensure that KLASS is completed if it is a dynamic type, or references
13922  * dynamic types.
13923  */
13924 static void
13925 ensure_complete_type (MonoClass *klass, MonoError *error)
13926 {
13927         mono_error_init (error);
13928
13929         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13930                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13931
13932                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13933                 return_if_nok (error);
13934
13935                 // Asserting here could break a lot of code
13936                 //g_assert (klass->wastypebuilder);
13937         }
13938
13939         if (klass->generic_class) {
13940                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13941                 int i;
13942
13943                 for (i = 0; i < inst->type_argc; ++i) {
13944                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13945                         return_if_nok (error);
13946                 }
13947         }
13948 }
13949
13950 static gpointer
13951 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13952 {
13953         gpointer result = NULL;
13954
13955         mono_error_init (error);
13956
13957         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13958                 result = mono_string_intern_checked ((MonoString*)obj, error);
13959                 return_val_if_nok (error, NULL);
13960                 *handle_class = mono_defaults.string_class;
13961                 g_assert (result);
13962         } else if (strcmp (obj->vtable->klass->name, "RuntimeType") == 0) {
13963                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13964                 return_val_if_nok (error, NULL);
13965                 MonoClass *mc = mono_class_from_mono_type (type);
13966                 if (!mono_class_init (mc)) {
13967                         mono_error_set_for_class_failure (error, mc);
13968                         return NULL;
13969                 }
13970
13971                 if (context) {
13972                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13973                         return_val_if_nok (error, NULL);
13974
13975                         result = mono_class_from_mono_type (inflated);
13976                         mono_metadata_free_type (inflated);
13977                 } else {
13978                         result = mono_class_from_mono_type (type);
13979                 }
13980                 *handle_class = mono_defaults.typehandle_class;
13981                 g_assert (result);
13982         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13983                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13984                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13985                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13986                 result = ((MonoReflectionMethod*)obj)->method;
13987                 if (context) {
13988                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13989                         mono_error_assert_ok (error);
13990                 }
13991                 *handle_class = mono_defaults.methodhandle_class;
13992                 g_assert (result);
13993         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13994                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13995                 result = mb->mhandle;
13996                 if (!result) {
13997                         /* Type is not yet created */
13998                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13999
14000                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14001                         return_val_if_nok (error, NULL);
14002
14003                         /*
14004                          * Hopefully this has been filled in by calling CreateType() on the
14005                          * TypeBuilder.
14006                          */
14007                         /*
14008                          * TODO: This won't work if the application finishes another 
14009                          * TypeBuilder instance instead of this one.
14010                          */
14011                         result = mb->mhandle;
14012                 }
14013                 if (context) {
14014                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14015                         mono_error_assert_ok (error);
14016                 }
14017                 *handle_class = mono_defaults.methodhandle_class;
14018         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
14019                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
14020
14021                 result = cb->mhandle;
14022                 if (!result) {
14023                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
14024
14025                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14026                         return_val_if_nok (error, NULL);
14027                         result = cb->mhandle;
14028                 }
14029                 if (context) {
14030                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14031                         mono_error_assert_ok (error);
14032                 }
14033                 *handle_class = mono_defaults.methodhandle_class;
14034         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
14035                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
14036
14037                 ensure_complete_type (field->parent, error);
14038                 return_val_if_nok (error, NULL);
14039
14040                 if (context) {
14041                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
14042                         return_val_if_nok (error, NULL);
14043
14044                         MonoClass *klass = mono_class_from_mono_type (inflated);
14045                         MonoClassField *inflated_field;
14046                         gpointer iter = NULL;
14047                         mono_metadata_free_type (inflated);
14048                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
14049                                 if (!strcmp (field->name, inflated_field->name))
14050                                         break;
14051                         }
14052                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
14053                         result = inflated_field;
14054                 } else {
14055                         result = field;
14056                 }
14057                 *handle_class = mono_defaults.fieldhandle_class;
14058                 g_assert (result);
14059         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
14060                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
14061                 result = fb->handle;
14062
14063                 if (!result) {
14064                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
14065
14066                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14067                         return_val_if_nok (error, NULL);
14068                         result = fb->handle;
14069                 }
14070
14071                 if (fb->handle && fb->handle->parent->generic_container) {
14072                         MonoClass *klass = fb->handle->parent;
14073                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
14074                         return_val_if_nok (error, NULL);
14075
14076                         MonoClass *inflated = mono_class_from_mono_type (type);
14077
14078                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
14079                         g_assert (result);
14080                         mono_metadata_free_type (type);
14081                 }
14082                 *handle_class = mono_defaults.fieldhandle_class;
14083         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
14084                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
14085                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
14086                 return_val_if_nok (error, NULL);
14087                 MonoClass *klass;
14088
14089                 klass = type->data.klass;
14090                 if (klass->wastypebuilder) {
14091                         /* Already created */
14092                         result = klass;
14093                 }
14094                 else {
14095                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14096                         return_val_if_nok (error, NULL);
14097                         result = type->data.klass;
14098                         g_assert (result);
14099                 }
14100                 *handle_class = mono_defaults.typehandle_class;
14101         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
14102                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
14103                 MonoMethodSignature *sig;
14104                 int nargs, i;
14105
14106                 if (helper->arguments)
14107                         nargs = mono_array_length (helper->arguments);
14108                 else
14109                         nargs = 0;
14110
14111                 sig = mono_metadata_signature_alloc (image, nargs);
14112                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
14113                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
14114
14115                 if (helper->unmanaged_call_conv) { /* unmanaged */
14116                         sig->call_convention = helper->unmanaged_call_conv - 1;
14117                         sig->pinvoke = TRUE;
14118                 } else if (helper->call_conv & 0x02) {
14119                         sig->call_convention = MONO_CALL_VARARG;
14120                 } else {
14121                         sig->call_convention = MONO_CALL_DEFAULT;
14122                 }
14123
14124                 sig->param_count = nargs;
14125                 /* TODO: Copy type ? */
14126                 sig->ret = helper->return_type->type;
14127                 for (i = 0; i < nargs; ++i) {
14128                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
14129                         if (!is_ok (error)) {
14130                                 image_g_free (image, sig);
14131                                 return NULL;
14132                         }
14133                 }
14134
14135                 result = sig;
14136                 *handle_class = NULL;
14137         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
14138                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
14139                 /* Already created by the managed code */
14140                 g_assert (method->mhandle);
14141                 result = method->mhandle;
14142                 *handle_class = mono_defaults.methodhandle_class;
14143         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
14144                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14145                 return_val_if_nok (error, NULL);
14146                 type = mono_class_inflate_generic_type_checked (type, context, error);
14147                 return_val_if_nok (error, NULL);
14148
14149                 result = mono_class_from_mono_type (type);
14150                 *handle_class = mono_defaults.typehandle_class;
14151                 g_assert (result);
14152                 mono_metadata_free_type (type);
14153         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
14154                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14155                 return_val_if_nok (error, NULL);
14156                 type = mono_class_inflate_generic_type_checked (type, context, error);
14157                 return_val_if_nok (error, NULL);
14158
14159                 result = mono_class_from_mono_type (type);
14160                 *handle_class = mono_defaults.typehandle_class;
14161                 g_assert (result);
14162                 mono_metadata_free_type (type);
14163         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
14164                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
14165                 MonoClass *inflated;
14166                 MonoType *type;
14167                 MonoClassField *field;
14168
14169                 if (is_sre_field_builder (mono_object_class (f->fb)))
14170                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
14171                 else if (is_sr_mono_field (mono_object_class (f->fb)))
14172                         field = ((MonoReflectionField*)f->fb)->field;
14173                 else
14174                         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)));
14175
14176                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
14177                 return_val_if_nok (error, NULL);
14178                 type = mono_class_inflate_generic_type_checked (finst, context, error);
14179                 return_val_if_nok (error, NULL);
14180
14181                 inflated = mono_class_from_mono_type (type);
14182
14183                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
14184                 ensure_complete_type (field->parent, error);
14185                 if (!is_ok (error)) {
14186                         mono_metadata_free_type (type);
14187                         return NULL;
14188                 }
14189
14190                 g_assert (result);
14191                 mono_metadata_free_type (type);
14192                 *handle_class = mono_defaults.fieldhandle_class;
14193         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
14194                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14195                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14196                 return_val_if_nok (error, NULL);
14197                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14198                 return_val_if_nok (error, NULL);
14199
14200                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14201                 MonoMethod *method;
14202
14203                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14204                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14205                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14206                         method = ((MonoReflectionMethod *)c->cb)->method;
14207                 else
14208                         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)));
14209
14210                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14211                 *handle_class = mono_defaults.methodhandle_class;
14212                 mono_metadata_free_type (type);
14213         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14214                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14215                 if (m->method_args) {
14216                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14217                         return_val_if_nok (error, NULL);
14218                         if (context) {
14219                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14220                                 mono_error_assert_ok (error);
14221                         }
14222                 } else {
14223                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14224                         return_val_if_nok (error, NULL);
14225                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14226                         return_val_if_nok (error, NULL);
14227
14228                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
14229                         MonoMethod *method;
14230
14231                         if (is_sre_method_builder (mono_object_class (m->mb)))
14232                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14233                         else if (is_sr_mono_method (mono_object_class (m->mb)))
14234                                 method = ((MonoReflectionMethod *)m->mb)->method;
14235                         else
14236                                 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)));
14237
14238                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14239                         mono_metadata_free_type (type);
14240                 }
14241                 *handle_class = mono_defaults.methodhandle_class;
14242         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14243                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14244                 MonoType *mtype;
14245                 MonoClass *klass;
14246                 MonoMethod *method;
14247                 gpointer iter;
14248                 char *name;
14249
14250                 mtype = mono_reflection_type_get_handle (m->parent, error);
14251                 return_val_if_nok (error, NULL);
14252                 klass = mono_class_from_mono_type (mtype);
14253
14254                 /* Find the method */
14255
14256                 name = mono_string_to_utf8_checked (m->name, error);
14257                 return_val_if_nok (error, NULL);
14258                 iter = NULL;
14259                 while ((method = mono_class_get_methods (klass, &iter))) {
14260                         if (!strcmp (method->name, name))
14261                                 break;
14262                 }
14263                 g_free (name);
14264
14265                 // FIXME:
14266                 g_assert (method);
14267                 // FIXME: Check parameters/return value etc. match
14268
14269                 result = method;
14270                 *handle_class = mono_defaults.methodhandle_class;
14271         } else if (is_sre_array (mono_object_get_class(obj)) ||
14272                                 is_sre_byref (mono_object_get_class(obj)) ||
14273                                 is_sre_pointer (mono_object_get_class(obj))) {
14274                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14275                 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14276                 return_val_if_nok (error, NULL);
14277
14278                 if (context) {
14279                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14280                         return_val_if_nok (error, NULL);
14281
14282                         result = mono_class_from_mono_type (inflated);
14283                         mono_metadata_free_type (inflated);
14284                 } else {
14285                         result = mono_class_from_mono_type (type);
14286                 }
14287                 *handle_class = mono_defaults.typehandle_class;
14288         } else {
14289                 g_print ("%s\n", obj->vtable->klass->name);
14290                 g_assert_not_reached ();
14291         }
14292         return result;
14293 }
14294
14295 #else /* DISABLE_REFLECTION_EMIT */
14296
14297 MonoArray*
14298 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
14299 {
14300         g_assert_not_reached ();
14301         return NULL;
14302 }
14303
14304 void
14305 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14306 {
14307         g_assert_not_reached ();
14308 }
14309
14310 void
14311 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14312 {
14313         g_assert_not_reached ();
14314 }
14315
14316 gboolean
14317 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
14318 {
14319         g_assert_not_reached ();
14320         return FALSE;
14321 }
14322
14323 void
14324 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14325 {
14326         g_assert_not_reached ();
14327 }
14328
14329 void
14330 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14331 {
14332         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14333 }
14334
14335 void
14336 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14337 {
14338         g_assert_not_reached ();
14339 }
14340
14341 void
14342 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14343 {
14344         g_assert_not_reached ();
14345 }
14346
14347 MonoReflectionModule *
14348 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14349 {
14350         g_assert_not_reached ();
14351         return NULL;
14352 }
14353
14354 guint32
14355 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14356 {
14357         g_assert_not_reached ();
14358         return 0;
14359 }
14360
14361 guint32
14362 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14363 {
14364         g_assert_not_reached ();
14365         return 0;
14366 }
14367
14368 guint32
14369 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
14370                          gboolean create_open_instance, gboolean register_token, MonoError *error)
14371 {
14372         g_assert_not_reached ();
14373         return 0;
14374 }
14375
14376 void
14377 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14378 {
14379 }
14380
14381 void
14382 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14383 {
14384         g_assert_not_reached ();
14385 }
14386
14387 void
14388 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14389 {
14390         mono_error_init (error);
14391         *overrides = NULL;
14392         *num_overrides = 0;
14393 }
14394
14395 MonoReflectionEvent *
14396 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14397 {
14398         g_assert_not_reached ();
14399         return NULL;
14400 }
14401
14402 MonoReflectionType*
14403 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14404 {
14405         g_assert_not_reached ();
14406         return NULL;
14407 }
14408
14409 void
14410 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14411 {
14412         g_assert_not_reached ();
14413 }
14414
14415 MonoArray *
14416 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14417 {
14418         g_assert_not_reached ();
14419         return NULL;
14420 }
14421
14422 MonoArray *
14423 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14424 {
14425         g_assert_not_reached ();
14426         return NULL;
14427 }
14428
14429 void 
14430 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14431 {
14432 }
14433
14434 gpointer
14435 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
14436 {
14437         mono_error_init (error);
14438         return NULL;
14439 }
14440
14441 MonoType*
14442 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14443 {
14444         mono_error_init (error);
14445         if (!ref)
14446                 return NULL;
14447         return ref->type;
14448 }
14449
14450 void
14451 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14452 {
14453         g_assert_not_reached ();
14454 }
14455
14456 #endif /* DISABLE_REFLECTION_EMIT */
14457
14458 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14459 const static guint32 declsec_flags_map[] = {
14460         0x00000000,                                     /* empty */
14461         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
14462         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
14463         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
14464         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
14465         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
14466         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
14467         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
14468         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
14469         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
14470         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
14471         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
14472         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
14473         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
14474         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
14475         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
14476         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
14477         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
14478         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
14479 };
14480
14481 /*
14482  * Returns flags that includes all available security action associated to the handle.
14483  * @token: metadata token (either for a class or a method)
14484  * @image: image where resides the metadata.
14485  */
14486 static guint32
14487 mono_declsec_get_flags (MonoImage *image, guint32 token)
14488 {
14489         int index = mono_metadata_declsec_from_index (image, token);
14490         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14491         guint32 result = 0;
14492         guint32 action;
14493         int i;
14494
14495         /* HasSecurity can be present for other, not specially encoded, attributes,
14496            e.g. SuppressUnmanagedCodeSecurityAttribute */
14497         if (index < 0)
14498                 return 0;
14499
14500         for (i = index; i < t->rows; i++) {
14501                 guint32 cols [MONO_DECL_SECURITY_SIZE];
14502
14503                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14504                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14505                         break;
14506
14507                 action = cols [MONO_DECL_SECURITY_ACTION];
14508                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14509                         result |= declsec_flags_map [action];
14510                 } else {
14511                         g_assert_not_reached ();
14512                 }
14513         }
14514         return result;
14515 }
14516
14517 /*
14518  * Get the security actions (in the form of flags) associated with the specified method.
14519  *
14520  * @method: The method for which we want the declarative security flags.
14521  * Return the declarative security flags for the method (only).
14522  *
14523  * Note: To keep MonoMethod size down we do not cache the declarative security flags
14524  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
14525  */
14526 guint32
14527 mono_declsec_flags_from_method (MonoMethod *method)
14528 {
14529         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14530                 /* FIXME: No cache (for the moment) */
14531                 guint32 idx = mono_method_get_index (method);
14532                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14533                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14534                 return mono_declsec_get_flags (method->klass->image, idx);
14535         }
14536         return 0;
14537 }
14538
14539 /*
14540  * Get the security actions (in the form of flags) associated with the specified class.
14541  *
14542  * @klass: The class for which we want the declarative security flags.
14543  * Return the declarative security flags for the class.
14544  *
14545  * Note: We cache the flags inside the MonoClass structure as this will get 
14546  *       called very often (at least for each method).
14547  */
14548 guint32
14549 mono_declsec_flags_from_class (MonoClass *klass)
14550 {
14551         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14552                 if (!klass->ext || !klass->ext->declsec_flags) {
14553                         guint32 idx;
14554
14555                         idx = mono_metadata_token_index (klass->type_token);
14556                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14557                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14558                         mono_loader_lock ();
14559                         mono_class_alloc_ext (klass);
14560                         mono_loader_unlock ();
14561                         /* we cache the flags on classes */
14562                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14563                 }
14564                 return klass->ext->declsec_flags;
14565         }
14566         return 0;
14567 }
14568
14569 /*
14570  * Get the security actions (in the form of flags) associated with the specified assembly.
14571  *
14572  * @assembly: The assembly for which we want the declarative security flags.
14573  * Return the declarative security flags for the assembly.
14574  */
14575 guint32
14576 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14577 {
14578         guint32 idx = 1; /* there is only one assembly */
14579         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14580         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14581         return mono_declsec_get_flags (assembly->image, idx);
14582 }
14583
14584
14585 /*
14586  * Fill actions for the specific index (which may either be an encoded class token or
14587  * an encoded method token) from the metadata image.
14588  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14589  */
14590 static MonoBoolean
14591 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14592         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14593 {
14594         MonoBoolean result = FALSE;
14595         MonoTableInfo *t;
14596         guint32 cols [MONO_DECL_SECURITY_SIZE];
14597         int index = mono_metadata_declsec_from_index (image, token);
14598         int i;
14599
14600         t  = &image->tables [MONO_TABLE_DECLSECURITY];
14601         for (i = index; i < t->rows; i++) {
14602                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14603
14604                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14605                         return result;
14606
14607                 /* if present only replace (class) permissions with method permissions */
14608                 /* if empty accept either class or method permissions */
14609                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14610                         if (!actions->demand.blob) {
14611                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14612                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14613                                 actions->demand.blob = (char*) (blob + 2);
14614                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14615                                 result = TRUE;
14616                         }
14617                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14618                         if (!actions->noncasdemand.blob) {
14619                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14620                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14621                                 actions->noncasdemand.blob = (char*) (blob + 2);
14622                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14623                                 result = TRUE;
14624                         }
14625                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14626                         if (!actions->demandchoice.blob) {
14627                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14628                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14629                                 actions->demandchoice.blob = (char*) (blob + 2);
14630                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14631                                 result = TRUE;
14632                         }
14633                 }
14634         }
14635
14636         return result;
14637 }
14638
14639 static MonoBoolean
14640 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14641         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14642 {
14643         guint32 idx = mono_metadata_token_index (klass->type_token);
14644         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14645         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14646         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14647 }
14648
14649 static MonoBoolean
14650 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14651         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14652 {
14653         guint32 idx = mono_method_get_index (method);
14654         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14655         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14656         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14657 }
14658
14659 /*
14660  * Collect all actions (that requires to generate code in mini) assigned for
14661  * the specified method.
14662  * Note: Don't use the content of actions if the function return FALSE.
14663  */
14664 MonoBoolean
14665 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14666 {
14667         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14668                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14669         MonoBoolean result = FALSE;
14670         guint32 flags;
14671
14672         /* quick exit if no declarative security is present in the metadata */
14673         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14674                 return FALSE;
14675
14676         /* we want the original as the wrapper is "free" of the security informations */
14677         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14678                 method = mono_marshal_method_from_wrapper (method);
14679                 if (!method)
14680                         return FALSE;
14681         }
14682
14683         /* First we look for method-level attributes */
14684         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14685                 mono_class_init (method->klass);
14686                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14687
14688                 result = mono_declsec_get_method_demands_params (method, demands, 
14689                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14690         }
14691
14692         /* Here we use (or create) the class declarative cache to look for demands */
14693         flags = mono_declsec_flags_from_class (method->klass);
14694         if (flags & mask) {
14695                 if (!result) {
14696                         mono_class_init (method->klass);
14697                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14698                 }
14699                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14700                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14701         }
14702
14703         /* The boolean return value is used as a shortcut in case nothing needs to
14704            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14705         return result;
14706 }
14707
14708
14709 /*
14710  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14711  *
14712  * Note: Don't use the content of actions if the function return FALSE.
14713  */
14714 MonoBoolean
14715 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14716 {
14717         MonoBoolean result = FALSE;
14718         guint32 flags;
14719
14720         /* quick exit if no declarative security is present in the metadata */
14721         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14722                 return FALSE;
14723
14724         /* we want the original as the wrapper is "free" of the security informations */
14725         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14726                 method = mono_marshal_method_from_wrapper (method);
14727                 if (!method)
14728                         return FALSE;
14729         }
14730
14731         /* results are independant - zeroize both */
14732         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14733         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14734
14735         /* First we look for method-level attributes */
14736         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14737                 mono_class_init (method->klass);
14738
14739                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14740                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14741         }
14742
14743         /* Here we use (or create) the class declarative cache to look for demands */
14744         flags = mono_declsec_flags_from_class (method->klass);
14745         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14746                 mono_class_init (method->klass);
14747
14748                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14749                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14750         }
14751
14752         return result;
14753 }
14754
14755 /*
14756  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14757  *
14758  * @klass       The inherited class - this is the class that provides the security check (attributes)
14759  * @demans      
14760  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14761  * 
14762  * Note: Don't use the content of actions if the function return FALSE.
14763  */
14764 MonoBoolean
14765 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14766 {
14767         MonoBoolean result = FALSE;
14768         guint32 flags;
14769
14770         /* quick exit if no declarative security is present in the metadata */
14771         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14772                 return FALSE;
14773
14774         /* Here we use (or create) the class declarative cache to look for demands */
14775         flags = mono_declsec_flags_from_class (klass);
14776         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14777                 mono_class_init (klass);
14778                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14779
14780                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14781                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14782         }
14783
14784         return result;
14785 }
14786
14787 /*
14788  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14789  *
14790  * Note: Don't use the content of actions if the function return FALSE.
14791  */
14792 MonoBoolean
14793 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14794 {
14795         /* quick exit if no declarative security is present in the metadata */
14796         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14797                 return FALSE;
14798
14799         /* we want the original as the wrapper is "free" of the security informations */
14800         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14801                 method = mono_marshal_method_from_wrapper (method);
14802                 if (!method)
14803                         return FALSE;
14804         }
14805
14806         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14807                 mono_class_init (method->klass);
14808                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14809
14810                 return mono_declsec_get_method_demands_params (method, demands, 
14811                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14812         }
14813         return FALSE;
14814 }
14815
14816
14817 static MonoBoolean
14818 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14819 {
14820         guint32 cols [MONO_DECL_SECURITY_SIZE];
14821         MonoTableInfo *t;
14822         int i;
14823
14824         int index = mono_metadata_declsec_from_index (image, token);
14825         if (index == -1)
14826                 return FALSE;
14827
14828         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14829         for (i = index; i < t->rows; i++) {
14830                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14831
14832                 /* shortcut - index are ordered */
14833                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14834                         return FALSE;
14835
14836                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14837                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14838                         entry->blob = (char*) (metadata + 2);
14839                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14840                         return TRUE;
14841                 }
14842         }
14843
14844         return FALSE;
14845 }
14846
14847 MonoBoolean
14848 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14849 {
14850         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14851                 guint32 idx = mono_method_get_index (method);
14852                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14853                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14854                 return get_declsec_action (method->klass->image, idx, action, entry);
14855         }
14856         return FALSE;
14857 }
14858
14859 MonoBoolean
14860 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14861 {
14862         /* use cache */
14863         guint32 flags = mono_declsec_flags_from_class (klass);
14864         if (declsec_flags_map [action] & flags) {
14865                 guint32 idx = mono_metadata_token_index (klass->type_token);
14866                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14867                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14868                 return get_declsec_action (klass->image, idx, action, entry);
14869         }
14870         return FALSE;
14871 }
14872
14873 MonoBoolean
14874 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14875 {
14876         guint32 idx = 1; /* there is only one assembly */
14877         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14878         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14879
14880         return get_declsec_action (assembly->image, idx, action, entry);
14881 }
14882
14883 gboolean
14884 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14885 {
14886         MonoObject *res, *exc;
14887         void *params [1];
14888         static MonoMethod *method = NULL;
14889
14890         mono_error_init (error);
14891
14892         if (method == NULL) {
14893                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14894                 g_assert (method);
14895         }
14896
14897         /* 
14898          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14899          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14900          */
14901         g_assert (mono_class_get_ref_info (klass));
14902         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14903
14904         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14905         return_val_if_nok (error, FALSE);
14906
14907         MonoError inner_error;
14908         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &inner_error);
14909
14910         if (exc || !is_ok (&inner_error)) {
14911                 mono_error_cleanup (&inner_error);
14912                 return FALSE;
14913         } else
14914                 return *(MonoBoolean*)mono_object_unbox (res);
14915 }
14916
14917 /**
14918  * mono_reflection_type_get_type:
14919  * @reftype: the System.Type object
14920  *
14921  * Returns the MonoType* associated with the C# System.Type object @reftype.
14922  */
14923 MonoType*
14924 mono_reflection_type_get_type (MonoReflectionType *reftype)
14925 {
14926         g_assert (reftype);
14927
14928         MonoError error;
14929         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14930         mono_error_assert_ok (&error);
14931         return result;
14932 }
14933
14934 /**
14935  * mono_reflection_assembly_get_assembly:
14936  * @refassembly: the System.Reflection.Assembly object
14937  *
14938  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14939  */
14940 MonoAssembly*
14941 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14942 {
14943         g_assert (refassembly);
14944
14945         return refassembly->assembly;
14946 }
14947