Merge pull request #3269 from alexanderkyte/silence_zero_len
[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         count -= not_visible;
1482
1483         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1484
1485         ainfo->image = image;
1486         ainfo->num_attrs = count;
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                         ainfo->attrs [index].data = saved;
1496                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1497                         index ++;
1498                 }
1499         }
1500
1501         return ainfo;
1502 }
1503
1504 #ifndef DISABLE_REFLECTION_EMIT
1505 /*
1506  * LOCKING: Acquires the loader lock. 
1507  */
1508 static void
1509 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1510 {
1511         MONO_REQ_GC_UNSAFE_MODE;
1512
1513         MonoCustomAttrInfo *ainfo, *tmp;
1514
1515         if (!cattrs || !mono_array_length (cattrs))
1516                 return;
1517
1518         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1519
1520         mono_loader_lock ();
1521         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1522         if (tmp)
1523                 mono_custom_attrs_free (tmp);
1524         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1525         mono_loader_unlock ();
1526
1527 }
1528 #endif
1529
1530 void
1531 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1532 {
1533         MONO_REQ_GC_NEUTRAL_MODE;
1534
1535         if (ainfo && !ainfo->cached)
1536                 g_free (ainfo);
1537 }
1538
1539 /*
1540  * idx is the table index of the object
1541  * type is one of MONO_CUSTOM_ATTR_*
1542  */
1543 static gboolean
1544 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1545 {
1546         MONO_REQ_GC_UNSAFE_MODE;
1547
1548         MonoDynamicTable *table;
1549         MonoReflectionCustomAttr *cattr;
1550         guint32 *values;
1551         guint32 count, i, token;
1552         char blob_size [6];
1553         char *p = blob_size;
1554         
1555         mono_error_init (error);
1556
1557         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1558         if (!cattrs)
1559                 return TRUE;
1560         count = mono_array_length (cattrs);
1561         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1562         table->rows += count;
1563         alloc_table (table, table->rows);
1564         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1565         idx <<= MONO_CUSTOM_ATTR_BITS;
1566         idx |= type;
1567         for (i = 0; i < count; ++i) {
1568                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1569                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1570                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1571                 if (!mono_error_ok (error)) goto fail;
1572                 type = mono_metadata_token_index (token);
1573                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1574                 switch (mono_metadata_token_table (token)) {
1575                 case MONO_TABLE_METHOD:
1576                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1577                         /*
1578                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1579                          * method, not the one returned by mono_image_create_token ().
1580                          */
1581                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1582                         break;
1583                 case MONO_TABLE_MEMBERREF:
1584                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1585                         break;
1586                 default:
1587                         g_warning ("got wrong token in custom attr");
1588                         continue;
1589                 }
1590                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1591                 p = blob_size;
1592                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1593                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1594                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1595                 values += MONO_CUSTOM_ATTR_SIZE;
1596                 ++table->next_idx;
1597         }
1598
1599         return TRUE;
1600
1601 fail:
1602         return FALSE;
1603 }
1604
1605 static void
1606 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1607 {
1608         MONO_REQ_GC_UNSAFE_MODE;
1609
1610         MonoDynamicTable *table;
1611         guint32 *values;
1612         guint32 count, i, idx;
1613         MonoReflectionPermissionSet *perm;
1614
1615         if (!permissions)
1616                 return;
1617
1618         count = mono_array_length (permissions);
1619         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1620         table->rows += count;
1621         alloc_table (table, table->rows);
1622
1623         for (i = 0; i < mono_array_length (permissions); ++i) {
1624                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1625
1626                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1627
1628                 idx = mono_metadata_token_index (parent_token);
1629                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1630                 switch (mono_metadata_token_table (parent_token)) {
1631                 case MONO_TABLE_TYPEDEF:
1632                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1633                         break;
1634                 case MONO_TABLE_METHOD:
1635                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1636                         break;
1637                 case MONO_TABLE_ASSEMBLY:
1638                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1639                         break;
1640                 default:
1641                         g_assert_not_reached ();
1642                 }
1643
1644                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1645                 values [MONO_DECL_SECURITY_PARENT] = idx;
1646                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1647
1648                 ++table->next_idx;
1649         }
1650 }
1651
1652 /*
1653  * Fill in the MethodDef and ParamDef tables for a method.
1654  * This is used for both normal methods and constructors.
1655  */
1656 static gboolean
1657 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1658 {
1659         MONO_REQ_GC_UNSAFE_MODE;
1660
1661         MonoDynamicTable *table;
1662         guint32 *values;
1663         guint i, count;
1664
1665         mono_error_init (error);
1666
1667         /* room in this table is already allocated */
1668         table = &assembly->tables [MONO_TABLE_METHOD];
1669         *mb->table_idx = table->next_idx ++;
1670         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1671         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1672         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
1673         return_val_if_nok (error, FALSE);
1674         values [MONO_METHOD_FLAGS] = mb->attrs;
1675         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1676         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1677         return_val_if_nok (error, FALSE);
1678         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1679         return_val_if_nok (error, FALSE);
1680
1681         table = &assembly->tables [MONO_TABLE_PARAM];
1682         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1683
1684         mono_image_add_decl_security (assembly, 
1685                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1686
1687         if (mb->pinfo) {
1688                 MonoDynamicTable *mtable;
1689                 guint32 *mvalues;
1690                 
1691                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1692                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1693                 
1694                 count = 0;
1695                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1696                         if (mono_array_get (mb->pinfo, gpointer, i))
1697                                 count++;
1698                 }
1699                 table->rows += count;
1700                 alloc_table (table, table->rows);
1701                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1702                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1703                         MonoReflectionParamBuilder *pb;
1704                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1705                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1706                                 values [MONO_PARAM_SEQUENCE] = i;
1707                                 if (pb->name != NULL) {
1708                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
1709                                         return_val_if_nok (error, FALSE);
1710                                 } else {
1711                                         values [MONO_PARAM_NAME] = 0;
1712                                 }
1713                                 values += MONO_PARAM_SIZE;
1714                                 if (pb->marshal_info) {
1715                                         mtable->rows++;
1716                                         alloc_table (mtable, mtable->rows);
1717                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1718                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1719                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1720                                         return_val_if_nok (error, FALSE);
1721                                 }
1722                                 pb->table_idx = table->next_idx++;
1723                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1724                                         guint32 field_type = 0;
1725                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1726                                         mtable->rows ++;
1727                                         alloc_table (mtable, mtable->rows);
1728                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1729                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1730                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1731                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1732                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1733                                 }
1734                         }
1735                 }
1736         }
1737
1738         return TRUE;
1739 }
1740
1741 #ifndef DISABLE_REFLECTION_EMIT
1742 static gboolean
1743 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1744 {
1745         MONO_REQ_GC_UNSAFE_MODE;
1746
1747         mono_error_init (error);
1748         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1749
1750         rmb->ilgen = mb->ilgen;
1751         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1752         return_val_if_nok (error, FALSE);
1753         rmb->parameters = mb->parameters;
1754         rmb->generic_params = mb->generic_params;
1755         rmb->generic_container = mb->generic_container;
1756         rmb->opt_types = NULL;
1757         rmb->pinfo = mb->pinfo;
1758         rmb->attrs = mb->attrs;
1759         rmb->iattrs = mb->iattrs;
1760         rmb->call_conv = mb->call_conv;
1761         rmb->code = mb->code;
1762         rmb->type = mb->type;
1763         rmb->name = mb->name;
1764         rmb->table_idx = &mb->table_idx;
1765         rmb->init_locals = mb->init_locals;
1766         rmb->skip_visibility = FALSE;
1767         rmb->return_modreq = mb->return_modreq;
1768         rmb->return_modopt = mb->return_modopt;
1769         rmb->param_modreq = mb->param_modreq;
1770         rmb->param_modopt = mb->param_modopt;
1771         rmb->permissions = mb->permissions;
1772         rmb->mhandle = mb->mhandle;
1773         rmb->nrefs = 0;
1774         rmb->refs = NULL;
1775
1776         if (mb->dll) {
1777                 rmb->charset = mb->charset;
1778                 rmb->extra_flags = mb->extra_flags;
1779                 rmb->native_cc = mb->native_cc;
1780                 rmb->dllentry = mb->dllentry;
1781                 rmb->dll = mb->dll;
1782         }
1783
1784         return TRUE;
1785 }
1786
1787 static gboolean
1788 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1789 {
1790         MONO_REQ_GC_UNSAFE_MODE;
1791
1792         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1793
1794         mono_error_init (error);
1795
1796         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1797
1798         rmb->ilgen = mb->ilgen;
1799         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1800         return_val_if_nok (error, FALSE);
1801         rmb->parameters = mb->parameters;
1802         rmb->generic_params = NULL;
1803         rmb->generic_container = NULL;
1804         rmb->opt_types = NULL;
1805         rmb->pinfo = mb->pinfo;
1806         rmb->attrs = mb->attrs;
1807         rmb->iattrs = mb->iattrs;
1808         rmb->call_conv = mb->call_conv;
1809         rmb->code = NULL;
1810         rmb->type = mb->type;
1811         rmb->name = mono_string_new (mono_domain_get (), name);
1812         rmb->table_idx = &mb->table_idx;
1813         rmb->init_locals = mb->init_locals;
1814         rmb->skip_visibility = FALSE;
1815         rmb->return_modreq = NULL;
1816         rmb->return_modopt = NULL;
1817         rmb->param_modreq = mb->param_modreq;
1818         rmb->param_modopt = mb->param_modopt;
1819         rmb->permissions = mb->permissions;
1820         rmb->mhandle = mb->mhandle;
1821         rmb->nrefs = 0;
1822         rmb->refs = NULL;
1823
1824         return TRUE;
1825 }
1826
1827 static void
1828 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1829 {
1830         MONO_REQ_GC_UNSAFE_MODE;
1831
1832         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1833
1834         rmb->ilgen = mb->ilgen;
1835         rmb->rtype = mb->rtype;
1836         rmb->parameters = mb->parameters;
1837         rmb->generic_params = NULL;
1838         rmb->generic_container = NULL;
1839         rmb->opt_types = NULL;
1840         rmb->pinfo = NULL;
1841         rmb->attrs = mb->attrs;
1842         rmb->iattrs = 0;
1843         rmb->call_conv = mb->call_conv;
1844         rmb->code = NULL;
1845         rmb->type = (MonoObject *) mb->owner;
1846         rmb->name = mb->name;
1847         rmb->table_idx = NULL;
1848         rmb->init_locals = mb->init_locals;
1849         rmb->skip_visibility = mb->skip_visibility;
1850         rmb->return_modreq = NULL;
1851         rmb->return_modopt = NULL;
1852         rmb->param_modreq = NULL;
1853         rmb->param_modopt = NULL;
1854         rmb->permissions = NULL;
1855         rmb->mhandle = mb->mhandle;
1856         rmb->nrefs = 0;
1857         rmb->refs = NULL;
1858 }       
1859 #endif
1860
1861 static gboolean
1862 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1863 {
1864         MONO_REQ_GC_UNSAFE_MODE;
1865
1866         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1867         MonoDynamicTable *table;
1868         guint32 *values;
1869         guint32 tok;
1870         MonoReflectionMethod *m;
1871         int i;
1872
1873         mono_error_init (error);
1874
1875         if (!mb->override_methods)
1876                 return TRUE;
1877
1878         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1879                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1880
1881                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1882                 table->rows ++;
1883                 alloc_table (table, table->rows);
1884                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1885                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1886                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1887
1888                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1889                 return_val_if_nok (error, FALSE);
1890
1891                 switch (mono_metadata_token_table (tok)) {
1892                 case MONO_TABLE_MEMBERREF:
1893                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1894                         break;
1895                 case MONO_TABLE_METHOD:
1896                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1897                         break;
1898                 default:
1899                         g_assert_not_reached ();
1900                 }
1901                 values [MONO_METHODIMPL_DECLARATION] = tok;
1902         }
1903
1904         return TRUE;
1905 }
1906
1907 #ifndef DISABLE_REFLECTION_EMIT
1908 static gboolean
1909 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1910 {
1911         MONO_REQ_GC_UNSAFE_MODE;
1912
1913         MonoDynamicTable *table;
1914         guint32 *values;
1915         ReflectionMethodBuilder rmb;
1916         int i;
1917
1918         mono_error_init (error);
1919
1920         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1921             !mono_image_basic_method (&rmb, assembly, error))
1922                 return FALSE;
1923
1924         mb->table_idx = *rmb.table_idx;
1925
1926         if (mb->dll) { /* It's a P/Invoke method */
1927                 guint32 moduleref;
1928                 /* map CharSet values to on-disk values */
1929                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1930                 int extra_flags = mb->extra_flags;
1931                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1932                 table->rows ++;
1933                 alloc_table (table, table->rows);
1934                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1935                 
1936                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1937                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1938                 if (mb->dllentry) {
1939                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry, error);
1940                         return_val_if_nok (error, FALSE);
1941                 } else {
1942                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
1943                         return_val_if_nok (error, FALSE);
1944                 }
1945                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll, error);
1946                 return_val_if_nok (error, FALSE);
1947                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1948                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1949                         table->rows ++;
1950                         alloc_table (table, table->rows);
1951                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1952                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1953                 }
1954         }
1955
1956         if (mb->generic_params) {
1957                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1958                 table->rows += mono_array_length (mb->generic_params);
1959                 alloc_table (table, table->rows);
1960                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1961                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1962
1963                         mono_image_get_generic_param_info (
1964                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1965                 }
1966         }
1967
1968         return TRUE;
1969 }
1970
1971 static gboolean
1972 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1973 {
1974         MONO_REQ_GC_UNSAFE_MODE;
1975
1976         ReflectionMethodBuilder rmb;
1977
1978         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1979                 return FALSE;
1980
1981         if (!mono_image_basic_method (&rmb, assembly, error))
1982                 return FALSE;
1983
1984         mb->table_idx = *rmb.table_idx;
1985
1986         return TRUE;
1987 }
1988 #endif
1989
1990 static char*
1991 type_get_fully_qualified_name (MonoType *type)
1992 {
1993         MONO_REQ_GC_NEUTRAL_MODE;
1994
1995         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1996 }
1997
1998 static char*
1999 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
2000 {
2001         MONO_REQ_GC_UNSAFE_MODE;
2002
2003         MonoClass *klass;
2004         MonoAssembly *ta;
2005
2006         klass = mono_class_from_mono_type (type);
2007         if (!klass) 
2008                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2009         ta = klass->image->assembly;
2010         if (assembly_is_dynamic (ta) || (ta == ass)) {
2011                 if (klass->generic_class || klass->generic_container)
2012                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
2013                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2014                 else
2015                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2016         }
2017
2018         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2019 }
2020
2021 #ifndef DISABLE_REFLECTION_EMIT
2022 /*field_image is the image to which the eventual custom mods have been encoded against*/
2023 static guint32
2024 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2025 {
2026         MONO_REQ_GC_NEUTRAL_MODE;
2027
2028         SigBuffer buf;
2029         guint32 idx, i, token;
2030
2031         if (!assembly->save)
2032                 return 0;
2033
2034         sigbuffer_init (&buf, 32);
2035         
2036         sigbuffer_add_value (&buf, 0x06);
2037         /* encode custom attributes before the type */
2038         if (type->num_mods) {
2039                 for (i = 0; i < type->num_mods; ++i) {
2040                         if (field_image) {
2041                                 MonoError error;
2042                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2043                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2044
2045                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2046                         } else {
2047                                 token = type->modifiers [i].token;
2048                         }
2049
2050                         if (type->modifiers [i].required)
2051                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2052                         else
2053                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2054
2055                         sigbuffer_add_value (&buf, token);
2056                 }
2057         }
2058         encode_type (assembly, type, &buf);
2059         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2060         sigbuffer_free (&buf);
2061         return idx;
2062 }
2063 #endif
2064
2065 static guint32
2066 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2067 {
2068         MONO_REQ_GC_UNSAFE_MODE;
2069
2070         mono_error_init (error);
2071
2072         SigBuffer buf;
2073         guint32 idx;
2074         guint32 typespec = 0;
2075         MonoType *type;
2076         MonoClass *klass;
2077
2078         init_type_builder_generics (fb->type, error);
2079         return_val_if_nok (error, 0);
2080
2081         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2082         return_val_if_nok (error, 0);
2083         klass = mono_class_from_mono_type (type);
2084
2085         sigbuffer_init (&buf, 32);
2086         
2087         sigbuffer_add_value (&buf, 0x06);
2088         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2089         if (!is_ok (error))
2090                 goto fail;
2091         /* encode custom attributes before the type */
2092
2093         if (klass->generic_container)
2094                 typespec = create_typespec (assembly, type);
2095
2096         if (typespec) {
2097                 MonoGenericClass *gclass;
2098                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2099                 encode_generic_class (assembly, gclass, &buf);
2100         } else {
2101                 encode_type (assembly, type, &buf);
2102         }
2103         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2104         sigbuffer_free (&buf);
2105         return idx;
2106 fail:
2107         sigbuffer_free (&buf);
2108         return 0;
2109 }
2110
2111 static guint32
2112 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2113 {
2114         MONO_REQ_GC_UNSAFE_MODE;
2115
2116         char blob_size [64];
2117         char *b = blob_size;
2118         char *box_val;
2119         char* buf;
2120         guint32 idx = 0, len = 0, dummy = 0;
2121
2122         buf = (char *)g_malloc (64);
2123         if (!val) {
2124                 *ret_type = MONO_TYPE_CLASS;
2125                 len = 4;
2126                 box_val = (char*)&dummy;
2127         } else {
2128                 box_val = ((char*)val) + sizeof (MonoObject);
2129                 *ret_type = val->vtable->klass->byval_arg.type;
2130         }
2131 handle_enum:
2132         switch (*ret_type) {
2133         case MONO_TYPE_BOOLEAN:
2134         case MONO_TYPE_U1:
2135         case MONO_TYPE_I1:
2136                 len = 1;
2137                 break;
2138         case MONO_TYPE_CHAR:
2139         case MONO_TYPE_U2:
2140         case MONO_TYPE_I2:
2141                 len = 2;
2142                 break;
2143         case MONO_TYPE_U4:
2144         case MONO_TYPE_I4:
2145         case MONO_TYPE_R4:
2146                 len = 4;
2147                 break;
2148         case MONO_TYPE_U8:
2149         case MONO_TYPE_I8:
2150                 len = 8;
2151                 break;
2152         case MONO_TYPE_R8:
2153                 len = 8;
2154                 break;
2155         case MONO_TYPE_VALUETYPE: {
2156                 MonoClass *klass = val->vtable->klass;
2157                 
2158                 if (klass->enumtype) {
2159                         *ret_type = mono_class_enum_basetype (klass)->type;
2160                         goto handle_enum;
2161                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2162                         len = 8;
2163                 } else 
2164                         g_error ("we can't encode valuetypes, we should have never reached this line");
2165                 break;
2166         }
2167         case MONO_TYPE_CLASS:
2168                 break;
2169         case MONO_TYPE_STRING: {
2170                 MonoString *str = (MonoString*)val;
2171                 /* there is no signature */
2172                 len = str->length * 2;
2173                 mono_metadata_encode_value (len, b, &b);
2174 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2175                 {
2176                         char *swapped = g_malloc (2 * mono_string_length (str));
2177                         const char *p = (const char*)mono_string_chars (str);
2178
2179                         swap_with_size (swapped, p, 2, mono_string_length (str));
2180                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2181                         g_free (swapped);
2182                 }
2183 #else
2184                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2185 #endif
2186
2187                 g_free (buf);
2188                 return idx;
2189         }
2190         case MONO_TYPE_GENERICINST:
2191                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2192                 goto handle_enum;
2193         default:
2194                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2195         }
2196
2197         /* there is no signature */
2198         mono_metadata_encode_value (len, b, &b);
2199 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2200         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2201         swap_with_size (blob_size, box_val, len, 1);
2202         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2203 #else
2204         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2205 #endif
2206
2207         g_free (buf);
2208         return idx;
2209 }
2210
2211 static guint32
2212 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2213 {
2214         MONO_REQ_GC_UNSAFE_MODE;
2215
2216         mono_error_init (error);
2217
2218         char *str;
2219         SigBuffer buf;
2220         guint32 idx, len;
2221
2222         sigbuffer_init (&buf, 32);
2223
2224         sigbuffer_add_value (&buf, minfo->type);
2225
2226         switch (minfo->type) {
2227         case MONO_NATIVE_BYVALTSTR:
2228         case MONO_NATIVE_BYVALARRAY:
2229                 sigbuffer_add_value (&buf, minfo->count);
2230                 break;
2231         case MONO_NATIVE_LPARRAY:
2232                 if (minfo->eltype || minfo->has_size) {
2233                         sigbuffer_add_value (&buf, minfo->eltype);
2234                         if (minfo->has_size) {
2235                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2236                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2237
2238                                 /* LAMESPEC: ElemMult is undocumented */
2239                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2240                         }
2241                 }
2242                 break;
2243         case MONO_NATIVE_SAFEARRAY:
2244                 if (minfo->eltype)
2245                         sigbuffer_add_value (&buf, minfo->eltype);
2246                 break;
2247         case MONO_NATIVE_CUSTOM:
2248                 if (minfo->guid) {
2249                         str = mono_string_to_utf8_checked (minfo->guid, error);
2250                         if (!is_ok (error)) {
2251                                 sigbuffer_free (&buf);
2252                                 return 0;
2253                         }
2254                         len = strlen (str);
2255                         sigbuffer_add_value (&buf, len);
2256                         sigbuffer_add_mem (&buf, str, len);
2257                         g_free (str);
2258                 } else {
2259                         sigbuffer_add_value (&buf, 0);
2260                 }
2261                 /* native type name */
2262                 sigbuffer_add_value (&buf, 0);
2263                 /* custom marshaler type name */
2264                 if (minfo->marshaltype || minfo->marshaltyperef) {
2265                         if (minfo->marshaltyperef) {
2266                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2267                                 if (!is_ok (error)) {
2268                                         sigbuffer_free (&buf);
2269                                         return 0;
2270                                 }
2271                                 str = type_get_fully_qualified_name (marshaltype);
2272                         } else {
2273                                 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
2274                                 if (!is_ok (error)) {
2275                                         sigbuffer_free (&buf);
2276                                         return 0;
2277                                 }
2278                         }
2279                         len = strlen (str);
2280                         sigbuffer_add_value (&buf, len);
2281                         sigbuffer_add_mem (&buf, str, len);
2282                         g_free (str);
2283                 } else {
2284                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2285                         sigbuffer_add_value (&buf, 0);
2286                 }
2287                 if (minfo->mcookie) {
2288                         str = mono_string_to_utf8_checked (minfo->mcookie, error);
2289                         if (!is_ok (error)) {
2290                                 sigbuffer_free (&buf);
2291                                 return 0;
2292                         }
2293                         len = strlen (str);
2294                         sigbuffer_add_value (&buf, len);
2295                         sigbuffer_add_mem (&buf, str, len);
2296                         g_free (str);
2297                 } else {
2298                         sigbuffer_add_value (&buf, 0);
2299                 }
2300                 break;
2301         default:
2302                 break;
2303         }
2304         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2305         sigbuffer_free (&buf);
2306         return idx;
2307 }
2308
2309 static void
2310 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2311 {
2312         MONO_REQ_GC_UNSAFE_MODE;
2313
2314         mono_error_init (error);
2315
2316         MonoDynamicTable *table;
2317         guint32 *values;
2318
2319         /* maybe this fixup should be done in the C# code */
2320         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2321                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2322         table = &assembly->tables [MONO_TABLE_FIELD];
2323         fb->table_idx = table->next_idx ++;
2324         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2325         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2326         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name, error);
2327         return_if_nok (error);
2328         values [MONO_FIELD_FLAGS] = fb->attrs;
2329         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2330         return_if_nok (error);
2331
2332
2333         if (fb->offset != -1) {
2334                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2335                 table->rows ++;
2336                 alloc_table (table, table->rows);
2337                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2338                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2339                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2340         }
2341         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2342                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2343                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2344                 table->rows ++;
2345                 alloc_table (table, table->rows);
2346                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2347                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2348                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2349                 values [MONO_CONSTANT_TYPE] = field_type;
2350                 values [MONO_CONSTANT_PADDING] = 0;
2351         }
2352         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2353                 guint32 rva_idx;
2354                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2355                 table->rows ++;
2356                 alloc_table (table, table->rows);
2357                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2358                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2359                 /*
2360                  * We store it in the code section because it's simpler for now.
2361                  */
2362                 if (fb->rva_data) {
2363                         if (mono_array_length (fb->rva_data) >= 10)
2364                                 stream_data_align (&assembly->code);
2365                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2366                 } else
2367                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2368                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2369         }
2370         if (fb->marshal_info) {
2371                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2372                 table->rows ++;
2373                 alloc_table (table, table->rows);
2374                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2375                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2376                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2377                 return_if_nok (error);
2378         }
2379 }
2380
2381 static guint32
2382 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2383 {
2384         MONO_REQ_GC_UNSAFE_MODE;
2385
2386         mono_error_init (error);
2387
2388         SigBuffer buf;
2389         guint32 nparams = 0;
2390         MonoReflectionMethodBuilder *mb = fb->get_method;
2391         MonoReflectionMethodBuilder *smb = fb->set_method;
2392         guint32 idx, i;
2393
2394         if (mb && mb->parameters)
2395                 nparams = mono_array_length (mb->parameters);
2396         if (!mb && smb && smb->parameters)
2397                 nparams = mono_array_length (smb->parameters) - 1;
2398         sigbuffer_init (&buf, 32);
2399         if (fb->call_conv & 0x20)
2400                 sigbuffer_add_byte (&buf, 0x28);
2401         else
2402                 sigbuffer_add_byte (&buf, 0x08);
2403         sigbuffer_add_value (&buf, nparams);
2404         if (mb) {
2405                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2406                 if (!is_ok (error))
2407                         goto fail;
2408                 for (i = 0; i < nparams; ++i) {
2409                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2410                         encode_reflection_type (assembly, pt, &buf, error);
2411                         if (!is_ok (error))
2412                                 goto fail;
2413                 }
2414         } else if (smb && smb->parameters) {
2415                 /* the property type is the last param */
2416                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2417                 if (!is_ok (error))
2418                         goto fail;
2419
2420                 for (i = 0; i < nparams; ++i) {
2421                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2422                         encode_reflection_type (assembly, pt, &buf, error);
2423                         if (!is_ok (error))
2424                                 goto fail;
2425                 }
2426         } else {
2427                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2428                 if (!is_ok (error))
2429                         goto fail;
2430         }
2431
2432         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2433         sigbuffer_free (&buf);
2434         return idx;
2435 fail:
2436         sigbuffer_free (&buf);
2437         return 0;
2438 }
2439
2440 static void
2441 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2442 {
2443         MONO_REQ_GC_UNSAFE_MODE;
2444
2445         mono_error_init (error);
2446
2447         MonoDynamicTable *table;
2448         guint32 *values;
2449         guint num_methods = 0;
2450         guint32 semaidx;
2451
2452         /* 
2453          * we need to set things in the following tables:
2454          * PROPERTYMAP (info already filled in _get_type_info ())
2455          * PROPERTY    (rows already preallocated in _get_type_info ())
2456          * METHOD      (method info already done with the generic method code)
2457          * METHODSEMANTICS
2458          * CONSTANT
2459          */
2460         table = &assembly->tables [MONO_TABLE_PROPERTY];
2461         pb->table_idx = table->next_idx ++;
2462         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2463         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
2464         return_if_nok (error);
2465         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2466         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2467         return_if_nok (error);
2468
2469
2470         /* FIXME: we still don't handle 'other' methods */
2471         if (pb->get_method) num_methods ++;
2472         if (pb->set_method) num_methods ++;
2473
2474         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2475         table->rows += num_methods;
2476         alloc_table (table, table->rows);
2477
2478         if (pb->get_method) {
2479                 semaidx = table->next_idx ++;
2480                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2481                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2482                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2483                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2484         }
2485         if (pb->set_method) {
2486                 semaidx = table->next_idx ++;
2487                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2488                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2489                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2490                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2491         }
2492         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2493                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2494                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2495                 table->rows ++;
2496                 alloc_table (table, table->rows);
2497                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2498                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2499                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2500                 values [MONO_CONSTANT_TYPE] = field_type;
2501                 values [MONO_CONSTANT_PADDING] = 0;
2502         }
2503 }
2504
2505 static void
2506 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2507 {
2508         MONO_REQ_GC_UNSAFE_MODE;
2509
2510         MonoDynamicTable *table;
2511         guint32 *values;
2512         guint num_methods = 0;
2513         guint32 semaidx;
2514
2515         /* 
2516          * we need to set things in the following tables:
2517          * EVENTMAP (info already filled in _get_type_info ())
2518          * EVENT    (rows already preallocated in _get_type_info ())
2519          * METHOD      (method info already done with the generic method code)
2520          * METHODSEMANTICS
2521          */
2522         table = &assembly->tables [MONO_TABLE_EVENT];
2523         eb->table_idx = table->next_idx ++;
2524         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2525         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name, error);
2526         return_if_nok (error);
2527         values [MONO_EVENT_FLAGS] = eb->attrs;
2528         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2529         return_if_nok (error);
2530         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2531
2532         /*
2533          * FIXME: we still don't handle 'other' methods 
2534          */
2535         if (eb->add_method) num_methods ++;
2536         if (eb->remove_method) num_methods ++;
2537         if (eb->raise_method) num_methods ++;
2538
2539         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2540         table->rows += num_methods;
2541         alloc_table (table, table->rows);
2542
2543         if (eb->add_method) {
2544                 semaidx = table->next_idx ++;
2545                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2546                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2547                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2548                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2549         }
2550         if (eb->remove_method) {
2551                 semaidx = table->next_idx ++;
2552                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2553                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2554                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2555                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2556         }
2557         if (eb->raise_method) {
2558                 semaidx = table->next_idx ++;
2559                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2560                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2561                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2562                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2563         }
2564 }
2565
2566 static void
2567 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2568 {
2569         MONO_REQ_GC_UNSAFE_MODE;
2570
2571         mono_error_init (error);
2572
2573         MonoDynamicTable *table;
2574         guint32 num_constraints, i;
2575         guint32 *values;
2576         guint32 table_idx;
2577
2578         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2579         num_constraints = gparam->iface_constraints ?
2580                 mono_array_length (gparam->iface_constraints) : 0;
2581         table->rows += num_constraints;
2582         if (gparam->base_type)
2583                 table->rows++;
2584         alloc_table (table, table->rows);
2585
2586         if (gparam->base_type) {
2587                 table_idx = table->next_idx ++;
2588                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2589
2590                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2591                 return_if_nok (error);
2592                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2593                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2594         }
2595
2596         for (i = 0; i < num_constraints; i++) {
2597                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2598                         gparam->iface_constraints, gpointer, i);
2599
2600                 table_idx = table->next_idx ++;
2601                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2602
2603                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2604                 return_if_nok (error);
2605
2606                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2607                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2608         }
2609 }
2610
2611 static void
2612 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2613 {
2614         MONO_REQ_GC_UNSAFE_MODE;
2615
2616         GenericParamTableEntry *entry;
2617
2618         /*
2619          * The GenericParam table must be sorted according to the `owner' field.
2620          * We need to do this sorting prior to writing the GenericParamConstraint
2621          * table, since we have to use the final GenericParam table indices there
2622          * and they must also be sorted.
2623          */
2624
2625         entry = g_new0 (GenericParamTableEntry, 1);
2626         entry->owner = owner;
2627         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2628         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2629         entry->gparam = gparam;
2630         
2631         g_ptr_array_add (assembly->gen_params, entry);
2632 }
2633
2634 static gboolean
2635 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2636 {
2637         MONO_REQ_GC_UNSAFE_MODE;
2638
2639         MonoDynamicTable *table;
2640         MonoGenericParam *param;
2641         guint32 *values;
2642         guint32 table_idx;
2643
2644         mono_error_init (error);
2645
2646         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2647         table_idx = table->next_idx ++;
2648         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2649
2650         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2651         return_val_if_nok (error, FALSE);
2652
2653         param = gparam_type->data.generic_param;
2654
2655         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2656         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2657         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2658         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2659
2660         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2661                 return FALSE;
2662
2663         encode_constraints (entry->gparam, table_idx, assembly, error);
2664         return_val_if_nok (error, FALSE);
2665
2666         return TRUE;
2667 }
2668
2669 static guint32
2670 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2671 {
2672         MONO_REQ_GC_UNSAFE_MODE;
2673
2674         MonoDynamicTable *table;
2675         guint32 token;
2676         guint32 *values;
2677         guint32 cols [MONO_ASSEMBLY_SIZE];
2678         const char *pubkey;
2679         guint32 publen;
2680
2681         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2682                 return token;
2683
2684         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2685                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2686                 token = table->next_idx ++;
2687                 table->rows ++;
2688                 alloc_table (table, table->rows);
2689                 values = table->values + token * MONO_MODULEREF_SIZE;
2690                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2691
2692                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2693                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2694                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2695
2696                 return token;
2697         }
2698         
2699         if (assembly_is_dynamic (image->assembly))
2700                 /* FIXME: */
2701                 memset (cols, 0, sizeof (cols));
2702         else {
2703                 /* image->assembly->image is the manifest module */
2704                 image = image->assembly->image;
2705                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2706         }
2707
2708         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2709         token = table->next_idx ++;
2710         table->rows ++;
2711         alloc_table (table, table->rows);
2712         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2713         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2714         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2715         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2716         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2717         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2718         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2719         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2720         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2721
2722         if (strcmp ("", image->assembly->aname.culture)) {
2723                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2724                                 image->assembly->aname.culture);
2725         }
2726
2727         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2728                 guchar pubtoken [9];
2729                 pubtoken [0] = 8;
2730                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2731                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2732         } else {
2733                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2734         }
2735         token <<= MONO_RESOLUTION_SCOPE_BITS;
2736         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2737         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2738         return token;
2739 }
2740
2741 static guint32
2742 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2743 {
2744         MONO_REQ_GC_NEUTRAL_MODE;
2745
2746         MonoDynamicTable *table;
2747         guint32 *values;
2748         guint32 token;
2749         SigBuffer buf;
2750
2751         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2752                 return token;
2753
2754         sigbuffer_init (&buf, 32);
2755         switch (type->type) {
2756         case MONO_TYPE_FNPTR:
2757         case MONO_TYPE_PTR:
2758         case MONO_TYPE_SZARRAY:
2759         case MONO_TYPE_ARRAY:
2760         case MONO_TYPE_VAR:
2761         case MONO_TYPE_MVAR:
2762         case MONO_TYPE_GENERICINST:
2763                 encode_type (assembly, type, &buf);
2764                 break;
2765         case MONO_TYPE_CLASS:
2766         case MONO_TYPE_VALUETYPE: {
2767                 MonoClass *k = mono_class_from_mono_type (type);
2768                 if (!k || !k->generic_container) {
2769                         sigbuffer_free (&buf);
2770                         return 0;
2771                 }
2772                 encode_type (assembly, type, &buf);
2773                 break;
2774         }
2775         default:
2776                 sigbuffer_free (&buf);
2777                 return 0;
2778         }
2779
2780         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2781         if (assembly->save) {
2782                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2783                 alloc_table (table, table->rows + 1);
2784                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2785                 values [MONO_TYPESPEC_SIGNATURE] = token;
2786         }
2787         sigbuffer_free (&buf);
2788
2789         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2790         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2791         table->next_idx ++;
2792         return token;
2793 }
2794
2795 static guint32
2796 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2797 {
2798         MONO_REQ_GC_UNSAFE_MODE;
2799
2800         MonoDynamicTable *table;
2801         guint32 *values;
2802         guint32 token, scope, enclosing;
2803         MonoClass *klass;
2804
2805         /* if the type requires a typespec, we must try that first*/
2806         if (try_typespec && (token = create_typespec (assembly, type)))
2807                 return token;
2808         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2809         if (token)
2810                 return token;
2811         klass = mono_class_from_mono_type (type);
2812         if (!klass)
2813                 klass = mono_class_from_mono_type (type);
2814
2815         /*
2816          * If it's in the same module and not a generic type parameter:
2817          */
2818         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2819                         (type->type != MONO_TYPE_MVAR)) {
2820                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2821                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2822                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2823                 return token;
2824         }
2825
2826         if (klass->nested_in) {
2827                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2828                 /* get the typeref idx of the enclosing type */
2829                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2830                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2831         } else {
2832                 scope = resolution_scope_from_image (assembly, klass->image);
2833         }
2834         table = &assembly->tables [MONO_TABLE_TYPEREF];
2835         if (assembly->save) {
2836                 alloc_table (table, table->rows + 1);
2837                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2838                 values [MONO_TYPEREF_SCOPE] = scope;
2839                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2840                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2841         }
2842         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2843         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2844         table->next_idx ++;
2845         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2846         return token;
2847 }
2848
2849 /*
2850  * Despite the name, we handle also TypeSpec (with the above helper).
2851  */
2852 static guint32
2853 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2854 {
2855         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2856 }
2857
2858 #ifndef DISABLE_REFLECTION_EMIT
2859 static guint32
2860 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2861 {
2862         MONO_REQ_GC_NEUTRAL_MODE;
2863
2864         MonoDynamicTable *table;
2865         guint32 *values;
2866         guint32 token, pclass;
2867
2868         switch (parent & MONO_TYPEDEFORREF_MASK) {
2869         case MONO_TYPEDEFORREF_TYPEREF:
2870                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2871                 break;
2872         case MONO_TYPEDEFORREF_TYPESPEC:
2873                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2874                 break;
2875         case MONO_TYPEDEFORREF_TYPEDEF:
2876                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2877                 break;
2878         default:
2879                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2880                 return 0;
2881         }
2882         /* extract the index */
2883         parent >>= MONO_TYPEDEFORREF_BITS;
2884
2885         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2886
2887         if (assembly->save) {
2888                 alloc_table (table, table->rows + 1);
2889                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2890                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2891                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2892                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2893         }
2894
2895         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2896         table->next_idx ++;
2897
2898         return token;
2899 }
2900
2901 /*
2902  * Insert a memberef row into the metadata: the token that point to the memberref
2903  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2904  * mono_image_get_fieldref_token()).
2905  * The sig param is an index to an already built signature.
2906  */
2907 static guint32
2908 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2909 {
2910         MONO_REQ_GC_NEUTRAL_MODE;
2911
2912         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2913         return mono_image_add_memberef_row (assembly, parent, name, sig);
2914 }
2915
2916
2917 static guint32
2918 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2919 {
2920         MONO_REQ_GC_NEUTRAL_MODE;
2921
2922         guint32 token;
2923         MonoMethodSignature *sig;
2924         
2925         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2926
2927         if (create_typespec) {
2928                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2929                 if (token)
2930                         return token;
2931         } 
2932
2933         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2934         if (token && !create_typespec)
2935                 return token;
2936
2937         g_assert (!method->is_inflated);
2938         if (!token) {
2939                 /*
2940                  * A methodref signature can't contain an unmanaged calling convention.
2941                  */
2942                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2943                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2944                         sig->call_convention = MONO_CALL_DEFAULT;
2945                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2946                         method->name,  method_encode_signature (assembly, sig));
2947                 g_free (sig);
2948                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2949         }
2950
2951         if (create_typespec) {
2952                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2953                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2954                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2955
2956                 if (assembly->save) {
2957                         guint32 *values;
2958
2959                         alloc_table (table, table->rows + 1);
2960                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2961                         values [MONO_METHODSPEC_METHOD] = token;
2962                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2963                 }
2964
2965                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2966                 table->next_idx ++;
2967                 /*methodspec and memberef tokens are diferent, */
2968                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2969                 return token;
2970         }
2971         return token;
2972 }
2973
2974 static guint32
2975 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2976 {
2977         guint32 token, parent, sig;
2978         ReflectionMethodBuilder rmb;
2979         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2980         
2981         mono_error_init (error);
2982         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2983         if (token)
2984                 return token;
2985
2986         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2987                 return 0;
2988
2989         /*
2990          * A methodref signature can't contain an unmanaged calling convention.
2991          * Since some flags are encoded as part of call_conv, we need to check against it.
2992         */
2993         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2994                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2995
2996         sig = method_builder_encode_signature (assembly, &rmb, error);
2997         return_val_if_nok (error, 0);
2998
2999         if (tb->generic_params) {
3000                 parent = create_generic_typespec (assembly, tb, error);
3001                 return_val_if_nok (error, 0);
3002         } else {
3003                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
3004                 return_val_if_nok (error, 0);
3005
3006                 parent = mono_image_typedef_or_ref (assembly, t);
3007         }
3008
3009         char *name = mono_string_to_utf8_checked (method->name, error);
3010         return_val_if_nok (error, 0);
3011
3012         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3013         g_free (name);
3014
3015         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3016
3017         return token;
3018 }
3019
3020 static guint32
3021 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
3022                                      const gchar *name, guint32 sig)
3023 {
3024         MonoDynamicTable *table;
3025         guint32 token;
3026         guint32 *values;
3027         
3028         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3029
3030         if (assembly->save) {
3031                 alloc_table (table, table->rows + 1);
3032                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3033                 values [MONO_MEMBERREF_CLASS] = original;
3034                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3035                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3036         }
3037
3038         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3039         table->next_idx ++;
3040
3041         return token;
3042 }
3043
3044 static guint32
3045 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3046 {
3047         SigBuffer buf;
3048         int i;
3049         guint32 nparams = mono_array_length (mb->generic_params);
3050         guint32 idx;
3051
3052         if (!assembly->save)
3053                 return 0;
3054
3055         sigbuffer_init (&buf, 32);
3056
3057         sigbuffer_add_value (&buf, 0xa);
3058         sigbuffer_add_value (&buf, nparams);
3059
3060         for (i = 0; i < nparams; i++) {
3061                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3062                 sigbuffer_add_value (&buf, i);
3063         }
3064
3065         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3066         sigbuffer_free (&buf);
3067         return idx;
3068 }
3069
3070 static guint32
3071 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3072 {
3073         MonoDynamicTable *table;
3074         guint32 *values;
3075         guint32 token, mtoken = 0;
3076
3077         mono_error_init (error);
3078         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3079         if (token)
3080                 return token;
3081
3082         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3083
3084         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3085         if (!mono_error_ok (error))
3086                 return 0;
3087
3088         switch (mono_metadata_token_table (mtoken)) {
3089         case MONO_TABLE_MEMBERREF:
3090                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3091                 break;
3092         case MONO_TABLE_METHOD:
3093                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3094                 break;
3095         default:
3096                 g_assert_not_reached ();
3097         }
3098
3099         if (assembly->save) {
3100                 alloc_table (table, table->rows + 1);
3101                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3102                 values [MONO_METHODSPEC_METHOD] = mtoken;
3103                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3104         }
3105
3106         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3107         table->next_idx ++;
3108
3109         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3110         return token;
3111 }
3112
3113 static guint32
3114 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3115 {
3116         guint32 token;
3117
3118         mono_error_init (error);
3119
3120         if (mb->generic_params && create_methodspec) 
3121                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3122
3123         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3124         if (token)
3125                 return token;
3126
3127         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3128         if (!mono_error_ok (error))
3129                 return 0;
3130         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3131         return token;
3132 }
3133
3134 static guint32
3135 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3136 {
3137         guint32 token, parent, sig;
3138         ReflectionMethodBuilder rmb;
3139         char *name;
3140         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3141         
3142         mono_error_init (error);
3143         
3144         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3145         if (token)
3146                 return token;
3147
3148         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3149                 return 0;
3150
3151         if (tb->generic_params) {
3152                 parent = create_generic_typespec (assembly, tb, error);
3153                 return_val_if_nok (error, 0);
3154         } else {
3155                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3156                 return_val_if_nok (error, 0);
3157                 parent = mono_image_typedef_or_ref (assembly, type);
3158         }
3159         
3160         name = mono_string_to_utf8_checked (rmb.name, error);
3161         return_val_if_nok (error, 0);
3162         sig = method_builder_encode_signature (assembly, &rmb, error);
3163         return_val_if_nok (error, 0);
3164
3165         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3166
3167         g_free (name);
3168         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3169         return token;
3170 }
3171 #endif
3172
3173 static gboolean
3174 is_field_on_inst (MonoClassField *field)
3175 {
3176         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3177 }
3178
3179 /*
3180  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3181  */
3182 static MonoType*
3183 get_field_on_inst_generic_type (MonoClassField *field)
3184 {
3185         MonoClass *klass, *gtd;
3186         MonoDynamicGenericClass *dgclass;
3187         int field_index;
3188
3189         g_assert (is_field_on_inst (field));
3190
3191         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3192
3193         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3194                 field_index = field - dgclass->fields;
3195                 return dgclass->field_generic_types [field_index];              
3196         }
3197
3198         klass = field->parent;
3199         gtd = klass->generic_class->container_class;
3200
3201         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3202                 field_index = field - klass->fields;
3203                 return gtd->fields [field_index].type;
3204         }
3205
3206         g_assert_not_reached ();
3207         return 0;
3208 }
3209
3210 #ifndef DISABLE_REFLECTION_EMIT
3211 static guint32
3212 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3213 {
3214         MonoType *type;
3215         guint32 token;
3216
3217         g_assert (field);
3218         g_assert (field->parent);
3219
3220         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3221         if (token)
3222                 return token;
3223
3224         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3225                 int index = field - field->parent->fields;
3226                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3227         } else {
3228                 if (is_field_on_inst (field))
3229                         type = get_field_on_inst_generic_type (field);
3230                 else
3231                         type = mono_field_get_type (field);
3232         }
3233         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3234                                                                                         mono_field_get_name (field),
3235                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3236         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3237         return token;
3238 }
3239
3240 static guint32
3241 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3242 {
3243         guint32 token;
3244         MonoClass *klass;
3245         MonoGenericClass *gclass;
3246         MonoType *type;
3247         char *name;
3248
3249         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3250         if (token)
3251                 return token;
3252         if (is_sre_field_builder (mono_object_class (f->fb))) {
3253                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3254                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3255                 return_val_if_nok (error, 0);
3256                 klass = mono_class_from_mono_type (type);
3257                 gclass = type->data.generic_class;
3258                 g_assert (gclass->is_dynamic);
3259
3260                 guint32 sig_token = field_encode_signature (assembly, fb, error);
3261                 return_val_if_nok (error, 0);
3262                 name = mono_string_to_utf8_checked (fb->name, error);
3263                 return_val_if_nok (error, 0);
3264                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3265                 g_free (name);          
3266         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3267                 guint32 sig;
3268                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3269
3270                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3271                 return_val_if_nok (error, 0);
3272                 klass = mono_class_from_mono_type (type);
3273
3274                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3275                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3276         } else {
3277                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3278                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3279         }
3280
3281         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3282         return token;
3283 }
3284
3285 static guint32
3286 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3287 {
3288         guint32 sig, token;
3289         MonoClass *klass;
3290         MonoGenericClass *gclass;
3291         MonoType *type;
3292
3293         mono_error_init (error);
3294
3295         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3296
3297         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3298         if (token)
3299                 return token;
3300
3301         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3302                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3303                 ReflectionMethodBuilder rmb;
3304                 char *name;
3305
3306                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3307                 return_val_if_nok (error, 0);
3308                 klass = mono_class_from_mono_type (type);
3309
3310                 gclass = type->data.generic_class;
3311                 g_assert (gclass->is_dynamic);
3312
3313                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3314                         return 0;
3315
3316                 sig = method_builder_encode_signature (assembly, &rmb, error);
3317                 return_val_if_nok (error, 0);
3318
3319                 name = mono_string_to_utf8_checked (rmb.name, error);
3320                 return_val_if_nok (error, 0);
3321
3322                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3323                 g_free (name);
3324         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3325                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3326
3327                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3328                 return_val_if_nok (error, 0);
3329                 klass = mono_class_from_mono_type (type);
3330
3331                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3332                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3333         } else {
3334                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3335                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3336         }
3337
3338
3339         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3340         return token;
3341 }
3342
3343 static MonoMethod*
3344 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3345 {
3346         MonoClass *klass;
3347         MonoGenericContext tmp_context;
3348         MonoType **type_argv;
3349         MonoGenericInst *ginst;
3350         MonoMethod *method, *inflated;
3351         int count, i;
3352
3353         mono_error_init (error);
3354
3355         init_type_builder_generics ((MonoObject*)m->inst, error);
3356         return_val_if_nok (error, NULL);
3357
3358         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3359         return_val_if_nok (error, NULL);
3360
3361         klass = method->klass;
3362
3363         if (m->method_args == NULL)
3364                 return method;
3365
3366         if (method->is_inflated)
3367                 method = ((MonoMethodInflated *) method)->declaring;
3368
3369         count = mono_array_length (m->method_args);
3370
3371         type_argv = g_new0 (MonoType *, count);
3372         for (i = 0; i < count; i++) {
3373                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3374                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3375                 return_val_if_nok (error, NULL);
3376         }
3377         ginst = mono_metadata_get_generic_inst (count, type_argv);
3378         g_free (type_argv);
3379
3380         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3381         tmp_context.method_inst = ginst;
3382
3383         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3384         mono_error_assert_ok (error);
3385         return inflated;
3386 }
3387
3388 static guint32
3389 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3390 {
3391         guint32 sig, token = 0;
3392         MonoType *type;
3393         MonoClass *klass;
3394
3395         mono_error_init (error);
3396
3397         if (m->method_args) {
3398                 MonoMethod *inflated;
3399
3400                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3401                 return_val_if_nok (error, 0);
3402
3403                 if (create_methodspec)
3404                         token = mono_image_get_methodspec_token (assembly, inflated);
3405                 else
3406                         token = mono_image_get_inflated_method_token (assembly, inflated);
3407                 return token;
3408         }
3409
3410         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3411         if (token)
3412                 return token;
3413
3414         if (is_sre_method_builder (mono_object_class (m->mb))) {
3415                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3416                 MonoGenericClass *gclass;
3417                 ReflectionMethodBuilder rmb;
3418                 char *name;
3419
3420                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3421                 return_val_if_nok (error, 0);
3422                 klass = mono_class_from_mono_type (type);
3423                 gclass = type->data.generic_class;
3424                 g_assert (gclass->is_dynamic);
3425
3426                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3427                         return 0;
3428
3429                 sig = method_builder_encode_signature (assembly, &rmb, error);
3430                 return_val_if_nok (error, 0);
3431
3432                 name = mono_string_to_utf8_checked (rmb.name, error);
3433                 return_val_if_nok (error, 0);
3434
3435                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3436                 g_free (name);          
3437         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3438                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3439
3440                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3441                 return_val_if_nok (error, 0);
3442                 klass = mono_class_from_mono_type (type);
3443
3444                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3445                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3446         } else {
3447                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3448                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3449         }
3450
3451         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3452         return token;
3453 }
3454
3455 static guint32
3456 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3457 {
3458         SigBuffer buf;
3459         int i;
3460         guint32 nparams = context->method_inst->type_argc;
3461         guint32 idx;
3462
3463         if (!assembly->save)
3464                 return 0;
3465
3466         sigbuffer_init (&buf, 32);
3467         /*
3468          * FIXME: vararg, explicit_this, differenc call_conv values...
3469          */
3470         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3471         sigbuffer_add_value (&buf, nparams);
3472
3473         for (i = 0; i < nparams; i++)
3474                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3475
3476         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3477         sigbuffer_free (&buf);
3478         return idx;
3479 }
3480
3481 static guint32
3482 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3483 {
3484         MonoDynamicTable *table;
3485         guint32 *values;
3486         guint32 token, mtoken = 0, sig;
3487         MonoMethodInflated *imethod;
3488         MonoMethod *declaring;
3489
3490         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3491
3492         g_assert (method->is_inflated);
3493         imethod = (MonoMethodInflated *) method;
3494         declaring = imethod->declaring;
3495
3496         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3497         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3498
3499         if (!mono_method_signature (declaring)->generic_param_count)
3500                 return mtoken;
3501
3502         switch (mono_metadata_token_table (mtoken)) {
3503         case MONO_TABLE_MEMBERREF:
3504                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3505                 break;
3506         case MONO_TABLE_METHOD:
3507                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3508                 break;
3509         default:
3510                 g_assert_not_reached ();
3511         }
3512
3513         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3514
3515         if (assembly->save) {
3516                 alloc_table (table, table->rows + 1);
3517                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3518                 values [MONO_METHODSPEC_METHOD] = mtoken;
3519                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3520         }
3521
3522         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3523         table->next_idx ++;
3524
3525         return token;
3526 }
3527
3528 static guint32
3529 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3530 {
3531         MonoMethodInflated *imethod;
3532         guint32 token;
3533         
3534         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3535         if (token)
3536                 return token;
3537
3538         g_assert (method->is_inflated);
3539         imethod = (MonoMethodInflated *) method;
3540
3541         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3542                 token = method_encode_methodspec (assembly, method);
3543         } else {
3544                 guint32 sig = method_encode_signature (
3545                         assembly, mono_method_signature (imethod->declaring));
3546                 token = mono_image_get_memberref_token (
3547                         assembly, &method->klass->byval_arg, method->name, sig);
3548         }
3549
3550         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3551         return token;
3552 }
3553
3554 static guint32
3555 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3556 {
3557         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3558         guint32 sig, token;
3559
3560         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3561         token = mono_image_get_memberref_token (
3562                 assembly, &m->klass->byval_arg, m->name, sig);
3563
3564         return token;
3565 }
3566
3567 static guint32
3568 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3569 {
3570         MonoDynamicTable *table;
3571         MonoClass *klass;
3572         MonoType *type;
3573         guint32 *values;
3574         guint32 token;
3575         SigBuffer buf;
3576         int count, i;
3577
3578         /*
3579          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3580          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3581          * Because of this, we must not insert it into the `typeref' hash table.
3582          */
3583         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3584         return_val_if_nok (error, 0);
3585         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3586         if (token)
3587                 return token;
3588
3589         sigbuffer_init (&buf, 32);
3590
3591         g_assert (tb->generic_params);
3592         klass = mono_class_from_mono_type (type);
3593
3594         if (tb->generic_container) {
3595                 if (!mono_reflection_create_generic_class (tb, error))
3596                         goto fail;
3597         }
3598
3599         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3600         g_assert (klass->generic_container);
3601         sigbuffer_add_value (&buf, klass->byval_arg.type);
3602         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3603
3604         count = mono_array_length (tb->generic_params);
3605         sigbuffer_add_value (&buf, count);
3606         for (i = 0; i < count; i++) {
3607                 MonoReflectionGenericParam *gparam;
3608
3609                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3610                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3611                 if (!is_ok (error))
3612                         goto fail;
3613
3614                 encode_type (assembly, gparam_type, &buf);
3615         }
3616
3617         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3618
3619         if (assembly->save) {
3620                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3621                 alloc_table (table, table->rows + 1);
3622                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3623                 values [MONO_TYPESPEC_SIGNATURE] = token;
3624         }
3625         sigbuffer_free (&buf);
3626
3627         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3628         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3629         table->next_idx ++;
3630         return token;
3631 fail:
3632         sigbuffer_free (&buf);
3633         return 0;
3634 }
3635
3636 /*
3637  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3638  */
3639 static MonoType*
3640 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3641 {
3642         int i, count, len, pos;
3643         MonoType *t;
3644
3645         mono_error_init (error);
3646
3647         count = 0;
3648         if (modreq)
3649                 count += mono_array_length (modreq);
3650         if (modopt)
3651                 count += mono_array_length (modopt);
3652
3653         if (count == 0)
3654                 return mono_metadata_type_dup (NULL, type);
3655
3656         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3657         t = (MonoType *)g_malloc (len);
3658         memcpy (t, type, MONO_SIZEOF_TYPE);
3659
3660         t->num_mods = count;
3661         pos = 0;
3662         if (modreq) {
3663                 for (i = 0; i < mono_array_length (modreq); ++i) {
3664                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3665                         if (!is_ok (error))
3666                                 goto fail;
3667                         t->modifiers [pos].required = 1;
3668                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3669                         pos ++;
3670                 }
3671         }
3672         if (modopt) {
3673                 for (i = 0; i < mono_array_length (modopt); ++i) {
3674                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3675                         if (!is_ok (error))
3676                                 goto fail;
3677                         t->modifiers [pos].required = 0;
3678                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3679                         pos ++;
3680                 }
3681         }
3682
3683         return t;
3684 fail:
3685         g_free (t);
3686         return NULL;
3687 }
3688
3689 static void
3690 init_type_builder_generics (MonoObject *type, MonoError *error)
3691 {
3692         MonoReflectionTypeBuilder *tb;
3693
3694         mono_error_init (error);
3695
3696         if (!is_sre_type_builder(mono_object_class (type)))
3697                 return;
3698         tb = (MonoReflectionTypeBuilder *)type;
3699
3700         if (tb && tb->generic_container)
3701                 mono_reflection_create_generic_class (tb, error);
3702 }
3703
3704 static guint32
3705 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3706 {
3707         MonoDynamicTable *table;
3708         MonoType *custom = NULL, *type;
3709         guint32 *values;
3710         guint32 token, pclass, parent, sig;
3711         gchar *name;
3712
3713         mono_error_init (error);
3714
3715         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3716         if (token)
3717                 return token;
3718
3719         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3720         return_val_if_nok (error, 0);
3721         /* FIXME: is this call necessary? */
3722         mono_class_from_mono_type (typeb);
3723
3724         /*FIXME this is one more layer of ugliness due how types are created.*/
3725         init_type_builder_generics (fb->type, error);
3726         return_val_if_nok (error, 0);
3727
3728         /* fb->type does not include the custom modifiers */
3729         /* FIXME: We should do this in one place when a fieldbuilder is created */
3730         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3731         return_val_if_nok (error, 0);
3732
3733         if (fb->modreq || fb->modopt) {
3734                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3735                 return_val_if_nok (error, 0);
3736         }
3737
3738         sig = fieldref_encode_signature (assembly, NULL, type);
3739         g_free (custom);
3740
3741         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3742         return_val_if_nok (error, 0);
3743         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3744         
3745         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3746         parent >>= MONO_TYPEDEFORREF_BITS;
3747
3748         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3749
3750         name = mono_string_to_utf8_checked (fb->name, error);
3751         return_val_if_nok (error, 0);
3752
3753         if (assembly->save) {
3754                 alloc_table (table, table->rows + 1);
3755                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3756                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3757                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3758                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3759         }
3760
3761         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3762         table->next_idx ++;
3763         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3764         g_free (name);
3765         return token;
3766 }
3767
3768 static guint32
3769 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3770 {
3771         SigBuffer buf;
3772         guint32 nargs;
3773         guint32 i, idx;
3774
3775         mono_error_init (error);
3776
3777         if (!assembly->save)
3778                 return 0;
3779
3780         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3781         g_assert (helper->type == 2);
3782
3783         if (helper->arguments)
3784                 nargs = mono_array_length (helper->arguments);
3785         else
3786                 nargs = 0;
3787
3788         sigbuffer_init (&buf, 32);
3789
3790         /* Encode calling convention */
3791         /* Change Any to Standard */
3792         if ((helper->call_conv & 0x03) == 0x03)
3793                 helper->call_conv = 0x01;
3794         /* explicit_this implies has_this */
3795         if (helper->call_conv & 0x40)
3796                 helper->call_conv &= 0x20;
3797
3798         if (helper->call_conv == 0) { /* Unmanaged */
3799                 idx = helper->unmanaged_call_conv - 1;
3800         } else {
3801                 /* Managed */
3802                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3803                 if (helper->call_conv & 0x02) /* varargs */
3804                         idx += 0x05;
3805         }
3806
3807         sigbuffer_add_byte (&buf, idx);
3808         sigbuffer_add_value (&buf, nargs);
3809         encode_reflection_type (assembly, helper->return_type, &buf, error);
3810         if (!is_ok (error))
3811                 goto fail;
3812         for (i = 0; i < nargs; ++i) {
3813                 MonoArray *modreqs = NULL;
3814                 MonoArray *modopts = NULL;
3815                 MonoReflectionType *pt;
3816
3817                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3818                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3819                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3820                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3821
3822                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3823                 if (!is_ok (error))
3824                         goto fail;
3825                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3826                 encode_reflection_type (assembly, pt, &buf, error);
3827                 if (!is_ok (error))
3828                         goto fail;
3829         }
3830         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3831         sigbuffer_free (&buf);
3832
3833         return idx;
3834 fail:
3835         sigbuffer_free (&buf);
3836         return 0;
3837 }
3838
3839 static guint32 
3840 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3841 {
3842         guint32 idx;
3843         MonoDynamicTable *table;
3844         guint32 *values;
3845
3846         mono_error_init (error);
3847
3848         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3849         idx = table->next_idx ++;
3850         table->rows ++;
3851         alloc_table (table, table->rows);
3852         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3853
3854         values [MONO_STAND_ALONE_SIGNATURE] =
3855                 mono_reflection_encode_sighelper (assembly, helper, error);
3856         return_val_if_nok (error, 0);
3857         
3858         return idx;
3859 }
3860
3861 static int
3862 reflection_cc_to_file (int call_conv) {
3863         switch (call_conv & 0x3) {
3864         case 0:
3865         case 1: return MONO_CALL_DEFAULT;
3866         case 2: return MONO_CALL_VARARG;
3867         default:
3868                 g_assert_not_reached ();
3869         }
3870         return 0;
3871 }
3872 #endif /* !DISABLE_REFLECTION_EMIT */
3873
3874 typedef struct {
3875         MonoType *parent;
3876         MonoMethodSignature *sig;
3877         char *name;
3878         guint32 token;
3879 } ArrayMethod;
3880
3881 #ifndef DISABLE_REFLECTION_EMIT
3882 static guint32
3883 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3884 {
3885         guint32 nparams, i;
3886         GList *tmp;
3887         char *name = NULL;
3888         MonoMethodSignature *sig;
3889         ArrayMethod *am = NULL;
3890         MonoType *mtype;
3891
3892         mono_error_init (error);
3893
3894         nparams = mono_array_length (m->parameters);
3895         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3896         sig->hasthis = 1;
3897         sig->sentinelpos = -1;
3898         sig->call_convention = reflection_cc_to_file (m->call_conv);
3899         sig->param_count = nparams;
3900         if (m->ret) {
3901                 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3902                 if (!is_ok (error))
3903                         goto fail;
3904         } else
3905                 sig->ret = &mono_defaults.void_class->byval_arg;
3906
3907         mtype = mono_reflection_type_get_handle (m->parent, error);
3908         if (!is_ok (error))
3909                 goto fail;
3910
3911         for (i = 0; i < nparams; ++i) {
3912                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3913                 if (!is_ok (error))
3914                         goto fail;
3915         }
3916
3917         name = mono_string_to_utf8_checked (m->name, error);
3918         if (!is_ok (error))
3919                 goto fail;
3920         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3921                 am = (ArrayMethod *)tmp->data;
3922                 if (strcmp (name, am->name) == 0 && 
3923                                 mono_metadata_type_equal (am->parent, mtype) &&
3924                                 mono_metadata_signature_equal (am->sig, sig)) {
3925                         g_free (name);
3926                         g_free (sig);
3927                         m->table_idx = am->token & 0xffffff;
3928                         return am->token;
3929                 }
3930         }
3931         am = g_new0 (ArrayMethod, 1);
3932         am->name = name;
3933         am->sig = sig;
3934         am->parent = mtype;
3935         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3936                 method_encode_signature (assembly, sig));
3937         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3938         m->table_idx = am->token & 0xffffff;
3939         return am->token;
3940 fail:
3941         g_free (am);
3942         g_free (name);
3943         g_free (sig);
3944         return 0;
3945
3946 }
3947
3948 /*
3949  * Insert into the metadata tables all the info about the TypeBuilder tb.
3950  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3951  */
3952 static gboolean
3953 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3954 {
3955         MonoDynamicTable *table;
3956         guint *values;
3957         int i, is_object = 0, is_system = 0;
3958         char *n;
3959
3960         mono_error_init (error);
3961
3962         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3963         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3964         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3965         n = mono_string_to_utf8_checked (tb->name, error);
3966         return_val_if_nok (error, FALSE);
3967         if (strcmp (n, "Object") == 0)
3968                 is_object++;
3969         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3970         g_free (n);
3971         n = mono_string_to_utf8_checked (tb->nspace, error);
3972         return_val_if_nok (error, FALSE);
3973         if (strcmp (n, "System") == 0)
3974                 is_system++;
3975         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3976         g_free (n);
3977         if (tb->parent && !(is_system && is_object) && 
3978                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3979                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3980                 return_val_if_nok (error, FALSE);
3981                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3982         } else {
3983                 values [MONO_TYPEDEF_EXTENDS] = 0;
3984         }
3985         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3986         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3987
3988         /*
3989          * if we have explicitlayout or sequentiallayouts, output data in the
3990          * ClassLayout table.
3991          */
3992         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3993                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3994                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3995                 table->rows++;
3996                 alloc_table (table, table->rows);
3997                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3998                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3999                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
4000                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
4001         }
4002
4003         /* handle interfaces */
4004         if (tb->interfaces) {
4005                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4006                 i = table->rows;
4007                 table->rows += mono_array_length (tb->interfaces);
4008                 alloc_table (table, table->rows);
4009                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
4010                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
4011                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
4012                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
4013                         return_val_if_nok (error, FALSE);
4014                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
4015                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
4016                         values += MONO_INTERFACEIMPL_SIZE;
4017                 }
4018         }
4019
4020         /* handle fields */
4021         if (tb->fields) {
4022                 table = &assembly->tables [MONO_TABLE_FIELD];
4023                 table->rows += tb->num_fields;
4024                 alloc_table (table, table->rows);
4025                 for (i = 0; i < tb->num_fields; ++i) {
4026                         mono_image_get_field_info (
4027                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
4028                         return_val_if_nok (error, FALSE);
4029                 }
4030         }
4031
4032         /* handle constructors */
4033         if (tb->ctors) {
4034                 table = &assembly->tables [MONO_TABLE_METHOD];
4035                 table->rows += mono_array_length (tb->ctors);
4036                 alloc_table (table, table->rows);
4037                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4038                         if (!mono_image_get_ctor_info (domain,
4039                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
4040                                                        assembly, error))
4041                                 return FALSE;
4042                 }
4043         }
4044
4045         /* handle methods */
4046         if (tb->methods) {
4047                 table = &assembly->tables [MONO_TABLE_METHOD];
4048                 table->rows += tb->num_methods;
4049                 alloc_table (table, table->rows);
4050                 for (i = 0; i < tb->num_methods; ++i) {
4051                         if (!mono_image_get_method_info (
4052                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4053                                 return FALSE;
4054                 }
4055         }
4056
4057         /* Do the same with properties etc.. */
4058         if (tb->events && mono_array_length (tb->events)) {
4059                 table = &assembly->tables [MONO_TABLE_EVENT];
4060                 table->rows += mono_array_length (tb->events);
4061                 alloc_table (table, table->rows);
4062                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4063                 table->rows ++;
4064                 alloc_table (table, table->rows);
4065                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4066                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4067                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4068                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4069                         mono_image_get_event_info (
4070                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4071                         return_val_if_nok (error, FALSE);
4072                 }
4073         }
4074         if (tb->properties && mono_array_length (tb->properties)) {
4075                 table = &assembly->tables [MONO_TABLE_PROPERTY];
4076                 table->rows += mono_array_length (tb->properties);
4077                 alloc_table (table, table->rows);
4078                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4079                 table->rows ++;
4080                 alloc_table (table, table->rows);
4081                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4082                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4083                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4084                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4085                         mono_image_get_property_info (
4086                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4087                         return_val_if_nok (error, FALSE);
4088                 }
4089         }
4090
4091         /* handle generic parameters */
4092         if (tb->generic_params) {
4093                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4094                 table->rows += mono_array_length (tb->generic_params);
4095                 alloc_table (table, table->rows);
4096                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4097                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4098
4099                         mono_image_get_generic_param_info (
4100                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4101                 }
4102         }
4103
4104         mono_image_add_decl_security (assembly, 
4105                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4106
4107         if (tb->subtypes) {
4108                 MonoDynamicTable *ntable;
4109                 
4110                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4111                 ntable->rows += mono_array_length (tb->subtypes);
4112                 alloc_table (ntable, ntable->rows);
4113                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4114
4115                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4116                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4117
4118                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4119                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4120                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4121                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4122                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4123                                 ntable->next_idx, ntable->rows);*/
4124                         values += MONO_NESTED_CLASS_SIZE;
4125                         ntable->next_idx++;
4126                 }
4127         }
4128
4129         return TRUE;
4130 }
4131 #endif
4132
4133 static void
4134 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4135 {
4136         int i;
4137
4138         mono_ptr_array_append (*types, type);
4139
4140         if (!type->subtypes)
4141                 return;
4142
4143         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4144                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4145                 collect_types (types, subtype);
4146         }
4147 }
4148
4149 static gint
4150 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4151 {
4152         if ((*type1)->table_idx < (*type2)->table_idx)
4153                 return -1;
4154         else
4155                 if ((*type1)->table_idx > (*type2)->table_idx)
4156                         return 1;
4157         else
4158                 return 0;
4159 }
4160
4161 static gboolean
4162 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4163         int i;
4164
4165         mono_error_init (error);
4166         if (!pinfo)
4167                 return TRUE;
4168         for (i = 0; i < mono_array_length (pinfo); ++i) {
4169                 MonoReflectionParamBuilder *pb;
4170                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4171                 if (!pb)
4172                         continue;
4173                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4174                         return FALSE;
4175         }
4176
4177         return TRUE;
4178 }
4179
4180 static gboolean
4181 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4182         int i;
4183
4184         mono_error_init (error);
4185         
4186         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4187                 return FALSE;
4188         if (tb->fields) {
4189                 for (i = 0; i < tb->num_fields; ++i) {
4190                         MonoReflectionFieldBuilder* fb;
4191                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4192                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4193                                 return FALSE;
4194                 }
4195         }
4196         if (tb->events) {
4197                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4198                         MonoReflectionEventBuilder* eb;
4199                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4200                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4201                                 return FALSE;
4202                 }
4203         }
4204         if (tb->properties) {
4205                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4206                         MonoReflectionPropertyBuilder* pb;
4207                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4208                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4209                                 return FALSE;
4210                 }
4211         }
4212         if (tb->ctors) {
4213                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4214                         MonoReflectionCtorBuilder* cb;
4215                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4216                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4217                             !params_add_cattrs (assembly, cb->pinfo, error))
4218                                 return FALSE;
4219                 }
4220         }
4221
4222         if (tb->methods) {
4223                 for (i = 0; i < tb->num_methods; ++i) {
4224                         MonoReflectionMethodBuilder* mb;
4225                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4226                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4227                             !params_add_cattrs (assembly, mb->pinfo, error))
4228                                 return FALSE;
4229                 }
4230         }
4231
4232         if (tb->subtypes) {
4233                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4234                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4235                                 return FALSE;
4236                 }
4237         }
4238
4239         return TRUE;
4240 }
4241
4242 static gboolean
4243 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4244 {
4245         int i;
4246         
4247         mono_error_init (error);
4248
4249         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4250                 return FALSE;
4251
4252         if (moduleb->global_methods) {
4253                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4254                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4255                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4256                             !params_add_cattrs (assembly, mb->pinfo, error))
4257                                 return FALSE;
4258                 }
4259         }
4260
4261         if (moduleb->global_fields) {
4262                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4263                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4264                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4265                                 return FALSE;
4266                 }
4267         }
4268         
4269         if (moduleb->types) {
4270                 for (i = 0; i < moduleb->num_types; ++i) {
4271                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4272                                 return FALSE;
4273                 }
4274         }
4275
4276         return TRUE;
4277 }
4278
4279 static gboolean
4280 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly, MonoError *error)
4281 {
4282         MonoDynamicTable *table;
4283         guint32 *values;
4284         char blob_size [6];
4285         guchar hash [20];
4286         char *b = blob_size;
4287         char *dir, *path;
4288
4289         mono_error_init (error);
4290
4291         table = &assembly->tables [MONO_TABLE_FILE];
4292         table->rows++;
4293         alloc_table (table, table->rows);
4294         values = table->values + table->next_idx * MONO_FILE_SIZE;
4295         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4296         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4297         if (image_is_dynamic (module->image)) {
4298                 /* This depends on the fact that the main module is emitted last */
4299                 dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, error);
4300                 return_val_if_nok (error, FALSE);
4301                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4302         } else {
4303                 dir = NULL;
4304                 path = g_strdup (module->image->name);
4305         }
4306         mono_sha1_get_digest_from_file (path, hash);
4307         g_free (dir);
4308         g_free (path);
4309         mono_metadata_encode_value (20, b, &b);
4310         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4311         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4312         table->next_idx ++;
4313         return TRUE;
4314 }
4315
4316 static void
4317 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
4318 {
4319         MonoDynamicTable *table;
4320         int i;
4321
4322         mono_error_init (error);
4323
4324         table = &assembly->tables [MONO_TABLE_MODULE];
4325         mb->table_idx = table->next_idx ++;
4326         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name, error);
4327         return_if_nok (error);
4328         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4329         i /= 16;
4330         ++i;
4331         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4332         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4333         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4334         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4335 }
4336
4337 static guint32
4338 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4339         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4340 {
4341         MonoDynamicTable *table;
4342         guint32 *values;
4343         guint32 visib, res;
4344
4345         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4346         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4347                 return 0;
4348
4349         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4350         table->rows++;
4351         alloc_table (table, table->rows);
4352         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4353
4354         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4355         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4356         if (klass->nested_in)
4357                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4358         else
4359                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4360         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4361         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4362
4363         res = table->next_idx;
4364
4365         table->next_idx ++;
4366
4367         /* Emit nested types */
4368         if (klass->ext && klass->ext->nested_classes) {
4369                 GList *tmp;
4370
4371                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4372                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4373         }
4374
4375         return res;
4376 }
4377
4378 static void
4379 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4380                               guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4381                               MonoError *error)
4382 {
4383         MonoClass *klass;
4384         guint32 idx, i;
4385
4386         mono_error_init (error);
4387
4388         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4389         return_if_nok (error);
4390
4391         klass = mono_class_from_mono_type (t);
4392
4393         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4394
4395         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4396                                                                                                    parent_index, assembly);
4397
4398         /* 
4399          * Emit nested types
4400          * We need to do this ourselves since klass->nested_classes is not set up.
4401          */
4402         if (tb->subtypes) {
4403                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4404                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4405                         return_if_nok (error);
4406                 }
4407         }
4408 }
4409
4410 static void
4411 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4412         guint32 module_index, MonoDynamicImage *assembly)
4413 {
4414         MonoImage *image = module->image;
4415         MonoTableInfo  *t;
4416         guint32 i;
4417
4418         t = &image->tables [MONO_TABLE_TYPEDEF];
4419
4420         for (i = 0; i < t->rows; ++i) {
4421                 MonoError error;
4422                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4423                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4424
4425                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4426                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4427         }
4428 }
4429
4430 static void
4431 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4432 {
4433         MonoDynamicTable *table;
4434         guint32 *values;
4435         guint32 scope, scope_idx, impl, current_idx;
4436         gboolean forwarder = TRUE;
4437         gpointer iter = NULL;
4438         MonoClass *nested;
4439
4440         if (klass->nested_in) {
4441                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4442                 forwarder = FALSE;
4443         } else {
4444                 scope = resolution_scope_from_image (assembly, klass->image);
4445                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4446                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4447                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4448         }
4449
4450         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4451
4452         table->rows++;
4453         alloc_table (table, table->rows);
4454         current_idx = table->next_idx;
4455         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4456
4457         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4458         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4459         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4460         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4461         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4462
4463         table->next_idx++;
4464
4465         while ((nested = mono_class_get_nested_types (klass, &iter)))
4466                 add_exported_type (assemblyb, assembly, nested, current_idx);
4467 }
4468
4469 static void
4470 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4471 {
4472         MonoError error;
4473         MonoClass *klass;
4474         int i;
4475
4476         if (!assemblyb->type_forwarders)
4477                 return;
4478
4479         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4480                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4481                 MonoType *type;
4482                 if (!t)
4483                         continue;
4484
4485                 type = mono_reflection_type_get_handle (t, &error);
4486                 mono_error_assert_ok (&error);
4487                 g_assert (type);
4488
4489                 klass = mono_class_from_mono_type (type);
4490
4491                 add_exported_type (assemblyb, assembly, klass, 0);
4492         }
4493 }
4494
4495 #define align_pointer(base,p)\
4496         do {\
4497                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4498                 if (__diff & 3)\
4499                         (p) += 4 - (__diff & 3);\
4500         } while (0)
4501
4502 static int
4503 compare_constants (const void *a, const void *b)
4504 {
4505         const guint32 *a_values = (const guint32 *)a;
4506         const guint32 *b_values = (const guint32 *)b;
4507         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4508 }
4509
4510 static int
4511 compare_semantics (const void *a, const void *b)
4512 {
4513         const guint32 *a_values = (const guint32 *)a;
4514         const guint32 *b_values = (const guint32 *)b;
4515         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4516         if (assoc)
4517                 return assoc;
4518         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4519 }
4520
4521 static int
4522 compare_custom_attrs (const void *a, const void *b)
4523 {
4524         const guint32 *a_values = (const guint32 *)a;
4525         const guint32 *b_values = (const guint32 *)b;
4526
4527         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4528 }
4529
4530 static int
4531 compare_field_marshal (const void *a, const void *b)
4532 {
4533         const guint32 *a_values = (const guint32 *)a;
4534         const guint32 *b_values = (const guint32 *)b;
4535
4536         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4537 }
4538
4539 static int
4540 compare_nested (const void *a, const void *b)
4541 {
4542         const guint32 *a_values = (const guint32 *)a;
4543         const guint32 *b_values = (const guint32 *)b;
4544
4545         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4546 }
4547
4548 static int
4549 compare_genericparam (const void *a, const void *b)
4550 {
4551         MonoError error;
4552         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4553         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4554
4555         if ((*b_entry)->owner == (*a_entry)->owner) {
4556                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4557                 mono_error_assert_ok (&error);
4558                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4559                 mono_error_assert_ok (&error);
4560                 return 
4561                         mono_type_get_generic_param_num (a_type) -
4562                         mono_type_get_generic_param_num (b_type);
4563         } else
4564                 return (*a_entry)->owner - (*b_entry)->owner;
4565 }
4566
4567 static int
4568 compare_declsecurity_attrs (const void *a, const void *b)
4569 {
4570         const guint32 *a_values = (const guint32 *)a;
4571         const guint32 *b_values = (const guint32 *)b;
4572
4573         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4574 }
4575
4576 static int
4577 compare_interface_impl (const void *a, const void *b)
4578 {
4579         const guint32 *a_values = (const guint32 *)a;
4580         const guint32 *b_values = (const guint32 *)b;
4581
4582         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4583         if (klass)
4584                 return klass;
4585
4586         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4587 }
4588
4589 static void
4590 pad_heap (MonoDynamicStream *sh)
4591 {
4592         if (sh->index & 3) {
4593                 int sz = 4 - (sh->index & 3);
4594                 memset (sh->data + sh->index, 0, sz);
4595                 sh->index += sz;
4596         }
4597 }
4598
4599 struct StreamDesc {
4600         const char *name;
4601         MonoDynamicStream *stream;
4602 };
4603
4604 /*
4605  * build_compressed_metadata() fills in the blob of data that represents the 
4606  * raw metadata as it will be saved in the PE file. The five streams are output 
4607  * and the metadata tables are comnpressed from the guint32 array representation, 
4608  * to the compressed on-disk format.
4609  */
4610 static gboolean
4611 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4612 {
4613         MonoDynamicTable *table;
4614         int i;
4615         guint64 valid_mask = 0;
4616         guint64 sorted_mask;
4617         guint32 heapt_size = 0;
4618         guint32 meta_size = 256; /* allow for header and other stuff */
4619         guint32 table_offset;
4620         guint32 ntables = 0;
4621         guint64 *int64val;
4622         guint32 *int32val;
4623         guint16 *int16val;
4624         MonoImage *meta;
4625         unsigned char *p;
4626         struct StreamDesc stream_desc [5];
4627
4628         mono_error_init (error);
4629
4630         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4631         for (i = 0; i < assembly->gen_params->len; i++) {
4632                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4633                 if (!write_generic_param_entry (assembly, entry, error))
4634                         return FALSE;
4635         }
4636
4637         stream_desc [0].name  = "#~";
4638         stream_desc [0].stream = &assembly->tstream;
4639         stream_desc [1].name  = "#Strings";
4640         stream_desc [1].stream = &assembly->sheap;
4641         stream_desc [2].name  = "#US";
4642         stream_desc [2].stream = &assembly->us;
4643         stream_desc [3].name  = "#Blob";
4644         stream_desc [3].stream = &assembly->blob;
4645         stream_desc [4].name  = "#GUID";
4646         stream_desc [4].stream = &assembly->guid;
4647         
4648         /* tables that are sorted */
4649         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4650                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4651                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4652                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4653                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4654                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4655                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4656         
4657         /* Compute table sizes */
4658         /* the MonoImage has already been created in mono_image_basic_init() */
4659         meta = &assembly->image;
4660
4661         /* sizes should be multiple of 4 */
4662         pad_heap (&assembly->blob);
4663         pad_heap (&assembly->guid);
4664         pad_heap (&assembly->sheap);
4665         pad_heap (&assembly->us);
4666
4667         /* Setup the info used by compute_sizes () */
4668         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4669         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4670         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4671
4672         meta_size += assembly->blob.index;
4673         meta_size += assembly->guid.index;
4674         meta_size += assembly->sheap.index;
4675         meta_size += assembly->us.index;
4676
4677         for (i=0; i < MONO_TABLE_NUM; ++i)
4678                 meta->tables [i].rows = assembly->tables [i].rows;
4679         
4680         for (i = 0; i < MONO_TABLE_NUM; i++){
4681                 if (meta->tables [i].rows == 0)
4682                         continue;
4683                 valid_mask |= (guint64)1 << i;
4684                 ntables ++;
4685                 meta->tables [i].row_size = mono_metadata_compute_size (
4686                         meta, i, &meta->tables [i].size_bitfield);
4687                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4688         }
4689         heapt_size += 24; /* #~ header size */
4690         heapt_size += ntables * 4;
4691         /* make multiple of 4 */
4692         heapt_size += 3;
4693         heapt_size &= ~3;
4694         meta_size += heapt_size;
4695         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4696         p = (unsigned char*)meta->raw_metadata;
4697         /* the metadata signature */
4698         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4699         /* version numbers and 4 bytes reserved */
4700         int16val = (guint16*)p;
4701         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4702         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4703         p += 8;
4704         /* version string */
4705         int32val = (guint32*)p;
4706         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4707         p += 4;
4708         memcpy (p, meta->version, strlen (meta->version));
4709         p += GUINT32_FROM_LE (*int32val);
4710         align_pointer (meta->raw_metadata, p);
4711         int16val = (guint16*)p;
4712         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4713         *int16val = GUINT16_TO_LE (5); /* number of streams */
4714         p += 4;
4715
4716         /*
4717          * write the stream info.
4718          */
4719         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4720         table_offset += 3; table_offset &= ~3;
4721
4722         assembly->tstream.index = heapt_size;
4723         for (i = 0; i < 5; ++i) {
4724                 int32val = (guint32*)p;
4725                 stream_desc [i].stream->offset = table_offset;
4726                 *int32val++ = GUINT32_TO_LE (table_offset);
4727                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4728                 table_offset += GUINT32_FROM_LE (*int32val);
4729                 table_offset += 3; table_offset &= ~3;
4730                 p += 8;
4731                 strcpy ((char*)p, stream_desc [i].name);
4732                 p += strlen (stream_desc [i].name) + 1;
4733                 align_pointer (meta->raw_metadata, p);
4734         }
4735         /* 
4736          * now copy the data, the table stream header and contents goes first.
4737          */
4738         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4739         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4740         int32val = (guint32*)p;
4741         *int32val = GUINT32_TO_LE (0); /* reserved */
4742         p += 4;
4743
4744         *p++ = 2; /* version */
4745         *p++ = 0;
4746
4747         if (meta->idx_string_wide)
4748                 *p |= 0x01;
4749         if (meta->idx_guid_wide)
4750                 *p |= 0x02;
4751         if (meta->idx_blob_wide)
4752                 *p |= 0x04;
4753         ++p;
4754         *p++ = 1; /* reserved */
4755         int64val = (guint64*)p;
4756         *int64val++ = GUINT64_TO_LE (valid_mask);
4757         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4758         p += 16;
4759         int32val = (guint32*)p;
4760         for (i = 0; i < MONO_TABLE_NUM; i++){
4761                 if (meta->tables [i].rows == 0)
4762                         continue;
4763                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4764         }
4765         p = (unsigned char*)int32val;
4766
4767         /* sort the tables that still need sorting */
4768         table = &assembly->tables [MONO_TABLE_CONSTANT];
4769         if (table->rows)
4770                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4771         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4772         if (table->rows)
4773                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4774         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4775         if (table->rows)
4776                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4777         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4778         if (table->rows)
4779                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4780         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4781         if (table->rows)
4782                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4783         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4784         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4785         if (table->rows)
4786                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4787         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4788         if (table->rows)
4789                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4790
4791         /* compress the tables */
4792         for (i = 0; i < MONO_TABLE_NUM; i++){
4793                 int row, col;
4794                 guint32 *values;
4795                 guint32 bitfield = meta->tables [i].size_bitfield;
4796                 if (!meta->tables [i].rows)
4797                         continue;
4798                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4799                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4800                 meta->tables [i].base = (char*)p;
4801                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4802                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4803                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4804                                 switch (mono_metadata_table_size (bitfield, col)) {
4805                                 case 1:
4806                                         *p++ = values [col];
4807                                         break;
4808                                 case 2:
4809                                         *p++ = values [col] & 0xff;
4810                                         *p++ = (values [col] >> 8) & 0xff;
4811                                         break;
4812                                 case 4:
4813                                         *p++ = values [col] & 0xff;
4814                                         *p++ = (values [col] >> 8) & 0xff;
4815                                         *p++ = (values [col] >> 16) & 0xff;
4816                                         *p++ = (values [col] >> 24) & 0xff;
4817                                         break;
4818                                 default:
4819                                         g_assert_not_reached ();
4820                                 }
4821                         }
4822                 }
4823                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4824         }
4825         
4826         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4827         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4828         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4829         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4830         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4831
4832         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4833
4834         return TRUE;
4835 }
4836
4837 /*
4838  * Some tables in metadata need to be sorted according to some criteria, but
4839  * when methods and fields are first created with reflection, they may be assigned a token
4840  * that doesn't correspond to the final token they will get assigned after the sorting.
4841  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4842  * with the reflection objects that represent them. Once all the tables are set up, the 
4843  * reflection objects will contains the correct table index. fixup_method() will fixup the
4844  * tokens for the method with ILGenerator @ilgen.
4845  */
4846 static void
4847 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4848 {
4849         guint32 code_idx = GPOINTER_TO_UINT (value);
4850         MonoReflectionILTokenInfo *iltoken;
4851         MonoReflectionFieldBuilder *field;
4852         MonoReflectionCtorBuilder *ctor;
4853         MonoReflectionMethodBuilder *method;
4854         MonoReflectionTypeBuilder *tb;
4855         MonoReflectionArrayMethod *am;
4856         guint32 i, idx = 0;
4857         unsigned char *target;
4858
4859         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4860                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4861                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4862                 switch (target [3]) {
4863                 case MONO_TABLE_FIELD:
4864                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4865                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4866                                 idx = field->table_idx;
4867                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4868                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4869                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4870                         } else {
4871                                 g_assert_not_reached ();
4872                         }
4873                         break;
4874                 case MONO_TABLE_METHOD:
4875                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4876                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4877                                 idx = method->table_idx;
4878                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4879                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4880                                 idx = ctor->table_idx;
4881                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4882                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4883                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4884                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4885                         } else {
4886                                 g_assert_not_reached ();
4887                         }
4888                         break;
4889                 case MONO_TABLE_TYPEDEF:
4890                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4891                                 g_assert_not_reached ();
4892                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4893                         idx = tb->table_idx;
4894                         break;
4895                 case MONO_TABLE_MEMBERREF:
4896                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4897                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4898                                 idx = am->table_idx;
4899                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4900                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4901                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4902                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4903                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4904                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4905                                 continue;
4906                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4907                                 continue;
4908                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4909                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4910                                 g_assert (is_field_on_inst (f));
4911                                 continue;
4912                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4913                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4914                                 continue;
4915                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4916                                 continue;
4917                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4918                                 continue;
4919                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4920                                 continue;
4921                         } else {
4922                                 g_assert_not_reached ();
4923                         }
4924                         break;
4925                 case MONO_TABLE_METHODSPEC:
4926                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4927                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4928                                 g_assert (mono_method_signature (m)->generic_param_count);
4929                                 continue;
4930                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4931                                 continue;
4932                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4933                                 continue;
4934                         } else {
4935                                 g_assert_not_reached ();
4936                         }
4937                         break;
4938                 default:
4939                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4940                 }
4941                 target [0] = idx & 0xff;
4942                 target [1] = (idx >> 8) & 0xff;
4943                 target [2] = (idx >> 16) & 0xff;
4944         }
4945 }
4946
4947 /*
4948  * fixup_cattrs:
4949  *
4950  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4951  * value is not known when the table is emitted.
4952  */
4953 static void
4954 fixup_cattrs (MonoDynamicImage *assembly)
4955 {
4956         MonoDynamicTable *table;
4957         guint32 *values;
4958         guint32 type, i, idx, token;
4959         MonoObject *ctor;
4960
4961         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4962
4963         for (i = 0; i < table->rows; ++i) {
4964                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4965
4966                 type = values [MONO_CUSTOM_ATTR_TYPE];
4967                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4968                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4969                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4970                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4971                         g_assert (ctor);
4972
4973                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4974                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4975                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4976                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4977                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4978                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4979                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4980                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4981                         }
4982                 }
4983         }
4984 }
4985
4986 static gboolean
4987 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
4988 {
4989         MonoDynamicTable *table;
4990         guint32 *values;
4991
4992         mono_error_init (error);
4993
4994         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4995         table->rows++;
4996         alloc_table (table, table->rows);
4997         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4998         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4999         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
5000         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
5001         return_val_if_nok (error, FALSE);
5002         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
5003         table->next_idx++;
5004         return TRUE;
5005 }
5006
5007 static gboolean
5008 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
5009 {
5010         MonoDynamicTable *table;
5011         guint32 *values;
5012         char blob_size [6];
5013         guchar hash [20];
5014         char *b = blob_size;
5015         char *name, *sname;
5016         guint32 idx, offset;
5017
5018         mono_error_init (error);
5019
5020         if (rsrc->filename) {
5021                 name = mono_string_to_utf8_checked (rsrc->filename, error);
5022                 return_val_if_nok (error, FALSE);
5023                 sname = g_path_get_basename (name);
5024         
5025                 table = &assembly->tables [MONO_TABLE_FILE];
5026                 table->rows++;
5027                 alloc_table (table, table->rows);
5028                 values = table->values + table->next_idx * MONO_FILE_SIZE;
5029                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
5030                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
5031                 g_free (sname);
5032
5033                 mono_sha1_get_digest_from_file (name, hash);
5034                 mono_metadata_encode_value (20, b, &b);
5035                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
5036                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
5037                 g_free (name);
5038                 idx = table->next_idx++;
5039                 rsrc->offset = 0;
5040                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
5041         } else {
5042                 char sizebuf [4];
5043                 char *data;
5044                 guint len;
5045                 if (rsrc->data) {
5046                         data = mono_array_addr (rsrc->data, char, 0);
5047                         len = mono_array_length (rsrc->data);
5048                 } else {
5049                         data = NULL;
5050                         len = 0;
5051                 }
5052                 offset = len;
5053                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
5054                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
5055                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
5056                 mono_image_add_stream_data (&assembly->resources, data, len);
5057
5058                 if (!mb->is_main)
5059                         /* 
5060                          * The entry should be emitted into the MANIFESTRESOURCE table of 
5061                          * the main module, but that needs to reference the FILE table
5062                          * which isn't emitted yet.
5063                          */
5064                         return TRUE;
5065                 else
5066                         idx = 0;
5067         }
5068
5069         return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
5070 }
5071
5072 static gboolean
5073 set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
5074 {
5075         gchar *ver, *p, *str;
5076         guint32 i;
5077         
5078         mono_error_init (error);
5079
5080         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5081         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5082         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5083         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5084         if (!version)
5085                 return TRUE;
5086         ver = str = mono_string_to_utf8_checked (version, error);
5087         return_val_if_nok (error, FALSE);
5088         for (i = 0; i < 4; ++i) {
5089                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5090                 switch (*p) {
5091                 case '.':
5092                         p++;
5093                         break;
5094                 case '*':
5095                         /* handle Revision and Build */
5096                         p++;
5097                         break;
5098                 }
5099                 ver = p;
5100         }
5101         g_free (str);
5102         return TRUE;
5103 }
5104
5105 static guint32
5106 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5107         gsize len;
5108         guint32 token = 0;
5109         char blob_size [6];
5110         char *b = blob_size;
5111
5112         if (!pkey)
5113                 return token;
5114
5115         len = mono_array_length (pkey);
5116         mono_metadata_encode_value (len, b, &b);
5117         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5118         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5119
5120         assembly->public_key = (guint8 *)g_malloc (len);
5121         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5122         assembly->public_key_len = len;
5123
5124         /* Special case: check for ECMA key (16 bytes) */
5125         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5126                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5127                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5128         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5129                 /* minimum key size (in 2.0) is 384 bits */
5130                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5131         } else {
5132                 /* FIXME - verifier */
5133                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5134                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5135         }
5136         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5137
5138         return token;
5139 }
5140
5141 static gboolean
5142 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5143 {
5144         MonoDynamicTable *table;
5145         MonoDynamicImage *assembly;
5146         MonoReflectionAssemblyBuilder *assemblyb;
5147         MonoDomain *domain;
5148         guint32 *values;
5149         int i;
5150         guint32 module_index;
5151
5152         mono_error_init (error);
5153
5154         assemblyb = moduleb->assemblyb;
5155         assembly = moduleb->dynamic_image;
5156         domain = mono_object_domain (assemblyb);
5157
5158         /* Emit ASSEMBLY table */
5159         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5160         alloc_table (table, 1);
5161         values = table->values + MONO_ASSEMBLY_SIZE;
5162         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5163         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
5164         return_val_if_nok (error, FALSE);
5165         if (assemblyb->culture) {
5166                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
5167                 return_val_if_nok (error, FALSE);
5168         } else {
5169                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5170         }
5171         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5172         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5173         if (!set_version_from_string (assemblyb->version, values, error))
5174                 return FALSE;
5175
5176         /* Emit FILE + EXPORTED_TYPE table */
5177         module_index = 0;
5178         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5179                 int j;
5180                 MonoReflectionModuleBuilder *file_module = 
5181                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5182                 if (file_module != moduleb) {
5183                         if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
5184                                 return FALSE;
5185                         module_index ++;
5186                         if (file_module->types) {
5187                                 for (j = 0; j < file_module->num_types; ++j) {
5188                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5189                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5190                                         return_val_if_nok (error, FALSE);
5191                                 }
5192                         }
5193                 }
5194         }
5195         if (assemblyb->loaded_modules) {
5196                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5197                         MonoReflectionModule *file_module = 
5198                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5199                         if (!mono_image_fill_file_table (domain, file_module, assembly, error))
5200                                 return FALSE;
5201                         module_index ++;
5202                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5203                 }
5204         }
5205         if (assemblyb->type_forwarders)
5206                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5207
5208         /* Emit MANIFESTRESOURCE table */
5209         module_index = 0;
5210         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5211                 int j;
5212                 MonoReflectionModuleBuilder *file_module = 
5213                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5214                 /* The table for the main module is emitted later */
5215                 if (file_module != moduleb) {
5216                         module_index ++;
5217                         if (file_module->resources) {
5218                                 int len = mono_array_length (file_module->resources);
5219                                 for (j = 0; j < len; ++j) {
5220                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5221                                         if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
5222                                                 return FALSE;
5223                                 }
5224                         }
5225                 }
5226         }
5227         return TRUE;
5228 }
5229
5230 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5231
5232 /*
5233  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5234  * for the modulebuilder @moduleb.
5235  * At the end of the process, method and field tokens are fixed up and the 
5236  * on-disk compressed metadata representation is created.
5237  * Return TRUE on success, or FALSE on failure and sets @error
5238  */
5239 gboolean
5240 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5241 {
5242         MonoDynamicTable *table;
5243         MonoDynamicImage *assembly;
5244         MonoReflectionAssemblyBuilder *assemblyb;
5245         MonoDomain *domain;
5246         MonoPtrArray types;
5247         guint32 *values;
5248         int i, j;
5249
5250         mono_error_init (error);
5251
5252         assemblyb = moduleb->assemblyb;
5253         assembly = moduleb->dynamic_image;
5254         domain = mono_object_domain (assemblyb);
5255
5256         if (assembly->text_rva)
5257                 return TRUE;
5258
5259         assembly->text_rva = START_TEXT_RVA;
5260
5261         if (moduleb->is_main) {
5262                 mono_image_emit_manifest (moduleb, error);
5263                 return_val_if_nok (error, FALSE);
5264         }
5265
5266         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5267         table->rows = 1; /* .<Module> */
5268         table->next_idx++;
5269         alloc_table (table, table->rows);
5270         /*
5271          * Set the first entry.
5272          */
5273         values = table->values + table->columns;
5274         values [MONO_TYPEDEF_FLAGS] = 0;
5275         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5276         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5277         values [MONO_TYPEDEF_EXTENDS] = 0;
5278         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5279         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5280
5281         /* 
5282          * handle global methods 
5283          * FIXME: test what to do when global methods are defined in multiple modules.
5284          */
5285         if (moduleb->global_methods) {
5286                 table = &assembly->tables [MONO_TABLE_METHOD];
5287                 table->rows += mono_array_length (moduleb->global_methods);
5288                 alloc_table (table, table->rows);
5289                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5290                         if (!mono_image_get_method_info (
5291                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5292                                 goto leave;
5293                 }
5294         }
5295         if (moduleb->global_fields) {
5296                 table = &assembly->tables [MONO_TABLE_FIELD];
5297                 table->rows += mono_array_length (moduleb->global_fields);
5298                 alloc_table (table, table->rows);
5299                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5300                         mono_image_get_field_info (
5301                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5302                                 error);
5303                         if (!is_ok (error))
5304                                 goto leave;
5305                 }
5306         }
5307
5308         table = &assembly->tables [MONO_TABLE_MODULE];
5309         alloc_table (table, 1);
5310         mono_image_fill_module_table (domain, moduleb, assembly, error);
5311         if (!is_ok (error))
5312                 goto leave;
5313
5314         /* Collect all types into a list sorted by their table_idx */
5315         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5316
5317         if (moduleb->types)
5318                 for (i = 0; i < moduleb->num_types; ++i) {
5319                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5320                         collect_types (&types, type);
5321                 }
5322
5323         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5324         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5325         table->rows += mono_ptr_array_size (types);
5326         alloc_table (table, table->rows);
5327
5328         /*
5329          * Emit type names + namespaces at one place inside the string heap,
5330          * so load_class_names () needs to touch fewer pages.
5331          */
5332         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5333                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5334                 string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
5335                 if (!is_ok (error))
5336                         goto leave_types;
5337         }
5338         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5339                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5340                 string_heap_insert_mstring (&assembly->sheap, tb->name, error);
5341                 if (!is_ok (error))
5342                         goto leave_types;
5343         }
5344
5345         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5346                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5347                 if (!mono_image_get_type_info (domain, type, assembly, error))
5348                         goto leave_types;
5349         }
5350
5351         /* 
5352          * table->rows is already set above and in mono_image_fill_module_table.
5353          */
5354         /* add all the custom attributes at the end, once all the indexes are stable */
5355         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5356                 goto leave_types;
5357
5358         /* CAS assembly permissions */
5359         if (assemblyb->permissions_minimum)
5360                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5361         if (assemblyb->permissions_optional)
5362                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5363         if (assemblyb->permissions_refused)
5364                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5365
5366         if (!module_add_cattrs (assembly, moduleb, error))
5367                 goto leave_types;
5368
5369         /* fixup tokens */
5370         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5371
5372         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5373          * the final tokens and don't need another fixup pass. */
5374
5375         if (moduleb->global_methods) {
5376                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5377                         MonoReflectionMethodBuilder *mb = mono_array_get (
5378                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5379                         if (!mono_image_add_methodimpl (assembly, mb, error))
5380                                 goto leave_types;
5381                 }
5382         }
5383
5384         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5385                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5386                 if (type->methods) {
5387                         for (j = 0; j < type->num_methods; ++j) {
5388                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5389                                         type->methods, MonoReflectionMethodBuilder*, j);
5390
5391                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5392                                         goto leave_types;
5393                         }
5394                 }
5395         }
5396
5397         fixup_cattrs (assembly);
5398
5399 leave_types:
5400         mono_ptr_array_destroy (types);
5401 leave:
5402
5403         return mono_error_ok (error);
5404 }
5405
5406 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5407
5408 gboolean
5409 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5410 {
5411         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5412 }
5413
5414 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5415
5416
5417 typedef struct {
5418         guint32 import_lookup_table;
5419         guint32 timestamp;
5420         guint32 forwarder;
5421         guint32 name_rva;
5422         guint32 import_address_table_rva;
5423 } MonoIDT;
5424
5425 typedef struct {
5426         guint32 name_rva;
5427         guint32 flags;
5428 } MonoILT;
5429
5430 #ifndef DISABLE_REFLECTION_EMIT
5431
5432 /*
5433  * mono_image_insert_string:
5434  * @module: module builder object
5435  * @str: a string
5436  *
5437  * Insert @str into the user string stream of @module.
5438  */
5439 guint32
5440 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5441 {
5442         MonoDynamicImage *assembly;
5443         guint32 idx;
5444         char buf [16];
5445         char *b = buf;
5446         
5447         if (!module->dynamic_image)
5448                 mono_image_module_basic_init (module);
5449
5450         assembly = module->dynamic_image;
5451         
5452         if (assembly->save) {
5453                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5454                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5455 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5456         {
5457                 char *swapped = g_malloc (2 * mono_string_length (str));
5458                 const char *p = (const char*)mono_string_chars (str);
5459
5460                 swap_with_size (swapped, p, 2, mono_string_length (str));
5461                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5462                 g_free (swapped);
5463         }
5464 #else
5465                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5466 #endif
5467                 mono_image_add_stream_data (&assembly->us, "", 1);
5468         } else {
5469                 idx = assembly->us.index ++;
5470         }
5471
5472         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5473
5474         return MONO_TOKEN_STRING | idx;
5475 }
5476
5477 guint32
5478 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5479 {
5480         MonoClass *klass;
5481         guint32 token = 0;
5482         MonoMethodSignature *sig;
5483
5484         mono_error_init (error);
5485
5486         klass = obj->vtable->klass;
5487         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5488                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5489                 MonoMethodSignature *old;
5490                 guint32 sig_token, parent;
5491                 int nargs, i;
5492
5493                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5494
5495                 nargs = mono_array_length (opt_param_types);
5496                 old = mono_method_signature (method);
5497                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5498
5499                 sig->hasthis = old->hasthis;
5500                 sig->explicit_this = old->explicit_this;
5501                 sig->call_convention = old->call_convention;
5502                 sig->generic_param_count = old->generic_param_count;
5503                 sig->param_count = old->param_count + nargs;
5504                 sig->sentinelpos = old->param_count;
5505                 sig->ret = old->ret;
5506
5507                 for (i = 0; i < old->param_count; i++)
5508                         sig->params [i] = old->params [i];
5509
5510                 for (i = 0; i < nargs; i++) {
5511                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5512                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5513                         if (!is_ok (error)) goto fail;
5514                 }
5515
5516                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5517                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5518                 parent >>= MONO_TYPEDEFORREF_BITS;
5519
5520                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5521                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5522
5523                 sig_token = method_encode_signature (assembly, sig);
5524                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5525         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5526                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5527                 ReflectionMethodBuilder rmb;
5528                 guint32 parent, sig_token;
5529                 int nopt_args, nparams, ngparams, i;
5530
5531                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5532                         goto fail;
5533                 
5534                 rmb.opt_types = opt_param_types;
5535                 nopt_args = mono_array_length (opt_param_types);
5536
5537                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5538                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5539                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5540
5541                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5542                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5543                 sig->call_convention = rmb.call_conv;
5544                 sig->generic_param_count = ngparams;
5545                 sig->param_count = nparams + nopt_args;
5546                 sig->sentinelpos = nparams;
5547                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5548                 if (!is_ok (error)) goto fail;
5549
5550                 for (i = 0; i < nparams; i++) {
5551                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5552                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5553                         if (!is_ok (error)) goto fail;
5554                 }
5555
5556                 for (i = 0; i < nopt_args; i++) {
5557                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5558                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5559                         if (!is_ok (error)) goto fail;
5560                 }
5561
5562                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5563                 if (!is_ok (error))
5564                         goto fail;
5565
5566                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5567                 if (!mono_error_ok (error))
5568                         goto fail;
5569                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5570
5571                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5572                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5573
5574                 char *name = mono_string_to_utf8_checked (rmb.name, error);
5575                 if (!is_ok (error)) goto fail;
5576                 token = mono_image_get_varargs_method_token (
5577                         assembly, parent, name, sig_token);
5578                 g_free (name);
5579         } else {
5580                 g_error ("requested method token for %s\n", klass->name);
5581         }
5582
5583         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5584         register_dyn_token (assembly, token, obj);
5585         return token;
5586 fail:
5587         g_assert (!mono_error_ok (error));
5588         return 0;
5589 }
5590
5591 /*
5592  * mono_image_create_token:
5593  * @assembly: a dynamic assembly
5594  * @obj:
5595  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5596  *
5597  * Get a token to insert in the IL code stream for the given MemberInfo.
5598  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5599  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5600  * entry.
5601  */
5602 guint32
5603 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5604                          gboolean create_open_instance, gboolean register_token,
5605                          MonoError *error)
5606 {
5607         MonoClass *klass;
5608         guint32 token = 0;
5609
5610         mono_error_init (error);
5611
5612         klass = obj->vtable->klass;
5613
5614         /* Check for user defined reflection objects */
5615         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5616         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5617                 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5618                 return 0;
5619         }
5620
5621         if (strcmp (klass->name, "MethodBuilder") == 0) {
5622                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5623                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5624
5625                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5626                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5627                 else {
5628                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5629                         if (!mono_error_ok (error))
5630                                 return 0;
5631                 }
5632                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5633         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5634                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5635                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5636
5637                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5638                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5639                 else {
5640                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5641                         if (!mono_error_ok (error))
5642                                 return 0;
5643                 }
5644                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5645         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5646                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5647                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5648                 if (tb->generic_params) {
5649                         token = mono_image_get_generic_field_token (assembly, fb, error);
5650                         return_val_if_nok (error, 0);
5651                 } else {
5652                         if (tb->module->dynamic_image == assembly) {
5653                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5654                         } else {
5655                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5656                         }
5657                 }
5658         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5659                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5660                 if (create_open_instance && tb->generic_params) {
5661                         MonoType *type;
5662                         init_type_builder_generics (obj, error);
5663                         return_val_if_nok (error, 0);
5664                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5665                         return_val_if_nok (error, 0);
5666                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5667                         token = mono_metadata_token_from_dor (token);
5668                 } else if (tb->module->dynamic_image == assembly) {
5669                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5670                 } else {
5671                         MonoType *type;
5672                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5673                         return_val_if_nok (error, 0);
5674                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5675                 }
5676         } else if (strcmp (klass->name, "RuntimeType") == 0) {
5677                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5678                 return_val_if_nok (error, 0);
5679                 MonoClass *mc = mono_class_from_mono_type (type);
5680                 token = mono_metadata_token_from_dor (
5681                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5682         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5683                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5684                 return_val_if_nok (error, 0);
5685                 token = mono_metadata_token_from_dor (
5686                         mono_image_typedef_or_ref (assembly, type));
5687         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5688                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5689                 return_val_if_nok (error, 0);
5690                 token = mono_metadata_token_from_dor (
5691                         mono_image_typedef_or_ref (assembly, type));
5692         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5693                    strcmp (klass->name, "MonoMethod") == 0 ||
5694                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5695                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5696                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5697                 if (m->method->is_inflated) {
5698                         if (create_open_instance)
5699                                 token = mono_image_get_methodspec_token (assembly, m->method);
5700                         else
5701                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5702                 } else if ((m->method->klass->image == &assembly->image) &&
5703                          !m->method->klass->generic_class) {
5704                         static guint32 method_table_idx = 0xffffff;
5705                         if (m->method->klass->wastypebuilder) {
5706                                 /* we use the same token as the one that was assigned
5707                                  * to the Methodbuilder.
5708                                  * FIXME: do the equivalent for Fields.
5709                                  */
5710                                 token = m->method->token;
5711                         } else {
5712                                 /*
5713                                  * Each token should have a unique index, but the indexes are
5714                                  * assigned by managed code, so we don't know about them. An
5715                                  * easy solution is to count backwards...
5716                                  */
5717                                 method_table_idx --;
5718                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5719                         }
5720                 } else {
5721                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5722                 }
5723                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5724         } else if (strcmp (klass->name, "MonoField") == 0) {
5725                 MonoReflectionField *f = (MonoReflectionField *)obj;
5726                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5727                         static guint32 field_table_idx = 0xffffff;
5728                         field_table_idx --;
5729                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5730                 } else {
5731                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5732                 }
5733                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5734         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5735                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5736                 token = mono_image_get_array_token (assembly, m, error);
5737                 return_val_if_nok (error, 0);
5738         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5739                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5740                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5741                 return_val_if_nok (error, 0);
5742         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5743                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5744                 return_val_if_nok (error, 0);
5745                 token = mono_metadata_token_from_dor (
5746                         mono_image_typedef_or_ref (assembly, type));
5747         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5748                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5749                 token = mono_image_get_field_on_inst_token (assembly, f, error);
5750                 return_val_if_nok (error, 0);
5751         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5752                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5753                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5754                 if (!mono_error_ok (error))
5755                         return 0;
5756         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5757                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5758                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5759                 if (!mono_error_ok (error))
5760                         return 0;
5761         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5762                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5763                 return_val_if_nok (error, 0);
5764                 token = mono_metadata_token_from_dor (
5765                                 mono_image_typedef_or_ref (assembly, type));
5766         } else {
5767                 g_error ("requested token for %s\n", klass->name);
5768         }
5769
5770         if (register_token)
5771                 mono_image_register_token (assembly, token, obj);
5772
5773         return token;
5774 }
5775
5776 /*
5777  * mono_image_register_token:
5778  *
5779  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5780  * the Module.ResolveXXXToken () methods to work.
5781  */
5782 void
5783 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5784 {
5785         MonoObject *prev;
5786
5787         dynamic_image_lock (assembly);
5788         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5789         if (prev) {
5790                 /* There could be multiple MethodInfo objects with the same token */
5791                 //g_assert (prev == obj);
5792         } else {
5793                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5794         }
5795         dynamic_image_unlock (assembly);
5796 }
5797
5798 static MonoDynamicImage*
5799 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5800 {
5801         static const guchar entrycode [16] = {0xff, 0x25, 0};
5802         MonoDynamicImage *image;
5803         int i;
5804
5805         const char *version;
5806
5807         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5808                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5809         else
5810                 version = mono_get_runtime_info ()->runtime_version;
5811
5812 #if HAVE_BOEHM_GC
5813         /* The MonoGHashTable's need GC tracking */
5814         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5815 #else
5816         image = g_new0 (MonoDynamicImage, 1);
5817 #endif
5818
5819         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5820         
5821         /*g_print ("created image %p\n", image);*/
5822         /* keep in sync with image.c */
5823         image->image.name = assembly_name;
5824         image->image.assembly_name = image->image.name; /* they may be different */
5825         image->image.module_name = module_name;
5826         image->image.version = g_strdup (version);
5827         image->image.md_version_major = 1;
5828         image->image.md_version_minor = 1;
5829         image->image.dynamic = TRUE;
5830
5831         image->image.references = g_new0 (MonoAssembly*, 1);
5832         image->image.references [0] = NULL;
5833
5834         mono_image_init (&image->image);
5835
5836         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");
5837         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5838         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5839         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5840         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5841         image->handleref = g_hash_table_new (NULL, NULL);
5842         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");
5843         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5844         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");
5845         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");
5846         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5847         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5848         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5849         image->gen_params = g_ptr_array_new ();
5850         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5851
5852         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5853         string_heap_init (&image->sheap);
5854         mono_image_add_stream_data (&image->us, "", 1);
5855         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5856         /* import tables... */
5857         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5858         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5859         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5860         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5861         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5862         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5863         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5864         stream_data_align (&image->code);
5865
5866         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5867
5868         for (i=0; i < MONO_TABLE_NUM; ++i) {
5869                 image->tables [i].next_idx = 1;
5870                 image->tables [i].columns = table_sizes [i];
5871         }
5872
5873         image->image.assembly = (MonoAssembly*)assembly;
5874         image->run = assembly->run;
5875         image->save = assembly->save;
5876         image->pe_kind = 0x1; /* ILOnly */
5877         image->machine = 0x14c; /* I386 */
5878         
5879         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5880
5881         dynamic_images_lock ();
5882
5883         if (!dynamic_images)
5884                 dynamic_images = g_ptr_array_new ();
5885
5886         g_ptr_array_add (dynamic_images, image);
5887
5888         dynamic_images_unlock ();
5889
5890         return image;
5891 }
5892 #endif
5893
5894 static void
5895 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5896 {
5897         g_free (key);
5898 }
5899
5900 static void
5901 release_hashtable (MonoGHashTable **hash)
5902 {
5903         if (*hash) {
5904                 mono_g_hash_table_destroy (*hash);
5905                 *hash = NULL;
5906         }
5907 }
5908
5909 void
5910 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5911 {
5912         release_hashtable (&image->token_fixups);
5913         release_hashtable (&image->handleref_managed);
5914         release_hashtable (&image->tokens);
5915         release_hashtable (&image->remapped_tokens);
5916         release_hashtable (&image->generic_def_objects);
5917         release_hashtable (&image->methodspec);
5918 }
5919
5920 // Free dynamic image pass one: Free resources but not image itself
5921 void
5922 mono_dynamic_image_free (MonoDynamicImage *image)
5923 {
5924         MonoDynamicImage *di = image;
5925         GList *list;
5926         int i;
5927
5928         if (di->methodspec)
5929                 mono_g_hash_table_destroy (di->methodspec);
5930         if (di->typespec)
5931                 g_hash_table_destroy (di->typespec);
5932         if (di->typeref)
5933                 g_hash_table_destroy (di->typeref);
5934         if (di->handleref)
5935                 g_hash_table_destroy (di->handleref);
5936         if (di->handleref_managed)
5937                 mono_g_hash_table_destroy (di->handleref_managed);
5938         if (di->tokens)
5939                 mono_g_hash_table_destroy (di->tokens);
5940         if (di->remapped_tokens)
5941                 mono_g_hash_table_destroy (di->remapped_tokens);
5942         if (di->generic_def_objects)
5943                 mono_g_hash_table_destroy (di->generic_def_objects);
5944         if (di->blob_cache) {
5945                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5946                 g_hash_table_destroy (di->blob_cache);
5947         }
5948         if (di->standalonesig_cache)
5949                 g_hash_table_destroy (di->standalonesig_cache);
5950         for (list = di->array_methods; list; list = list->next) {
5951                 ArrayMethod *am = (ArrayMethod *)list->data;
5952                 g_free (am->sig);
5953                 g_free (am->name);
5954                 g_free (am);
5955         }
5956         g_list_free (di->array_methods);
5957         if (di->gen_params) {
5958                 for (i = 0; i < di->gen_params->len; i++) {
5959                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5960                         mono_gc_deregister_root ((char*) &entry->gparam);
5961                         g_free (entry);
5962                 }
5963                 g_ptr_array_free (di->gen_params, TRUE);
5964         }
5965         if (di->token_fixups)
5966                 mono_g_hash_table_destroy (di->token_fixups);
5967         if (di->method_to_table_idx)
5968                 g_hash_table_destroy (di->method_to_table_idx);
5969         if (di->field_to_table_idx)
5970                 g_hash_table_destroy (di->field_to_table_idx);
5971         if (di->method_aux_hash)
5972                 g_hash_table_destroy (di->method_aux_hash);
5973         if (di->vararg_aux_hash)
5974                 g_hash_table_destroy (di->vararg_aux_hash);
5975         g_free (di->strong_name);
5976         g_free (di->win32_res);
5977         if (di->public_key)
5978                 g_free (di->public_key);
5979
5980         /*g_print ("string heap destroy for image %p\n", di);*/
5981         mono_dynamic_stream_reset (&di->sheap);
5982         mono_dynamic_stream_reset (&di->code);
5983         mono_dynamic_stream_reset (&di->resources);
5984         mono_dynamic_stream_reset (&di->us);
5985         mono_dynamic_stream_reset (&di->blob);
5986         mono_dynamic_stream_reset (&di->tstream);
5987         mono_dynamic_stream_reset (&di->guid);
5988         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5989                 g_free (di->tables [i].values);
5990         }
5991
5992         dynamic_images_lock ();
5993
5994         if (dynamic_images)
5995                 g_ptr_array_remove (dynamic_images, di);
5996
5997         dynamic_images_unlock ();
5998 }
5999
6000 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
6001 void
6002 mono_dynamic_image_free_image (MonoDynamicImage *image)
6003 {
6004         /* See create_dynamic_mono_image () */
6005 #if HAVE_BOEHM_GC
6006         /* Allocated using GC_MALLOC */
6007 #else
6008         g_free (image);
6009 #endif
6010 }
6011
6012 #ifndef DISABLE_REFLECTION_EMIT
6013
6014 /*
6015  * mono_image_basic_init:
6016  * @assembly: an assembly builder object
6017  *
6018  * Create the MonoImage that represents the assembly builder and setup some
6019  * of the helper hash table and the basic metadata streams.
6020  */
6021 void
6022 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
6023 {
6024         MonoError error;
6025         MonoDynamicAssembly *assembly;
6026         MonoDynamicImage *image;
6027         MonoDomain *domain = mono_object_domain (assemblyb);
6028         
6029         if (assemblyb->dynamic_assembly)
6030                 return;
6031
6032 #if HAVE_BOEHM_GC
6033         /* assembly->assembly.image might be GC allocated */
6034         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
6035 #else
6036         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
6037 #endif
6038
6039         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
6040         
6041         assembly->assembly.ref_count = 1;
6042         assembly->assembly.dynamic = TRUE;
6043         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
6044         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
6045         assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
6046         if (mono_error_set_pending_exception (&error))
6047                 return;
6048         if (assemblyb->culture) {
6049                 assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
6050                 if (mono_error_set_pending_exception (&error))
6051                         return;
6052         } else
6053                 assembly->assembly.aname.culture = g_strdup ("");
6054
6055         if (assemblyb->version) {
6056                         char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
6057                         if (mono_error_set_pending_exception (&error))
6058                                 return;
6059                         char **version = g_strsplit (vstr, ".", 4);
6060                         char **parts = version;
6061                         assembly->assembly.aname.major = atoi (*parts++);
6062                         assembly->assembly.aname.minor = atoi (*parts++);
6063                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
6064                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
6065
6066                         g_strfreev (version);
6067                         g_free (vstr);
6068         } else {
6069                         assembly->assembly.aname.major = 0;
6070                         assembly->assembly.aname.minor = 0;
6071                         assembly->assembly.aname.build = 0;
6072                         assembly->assembly.aname.revision = 0;
6073         }
6074
6075         assembly->run = assemblyb->access != 2;
6076         assembly->save = assemblyb->access != 1;
6077         assembly->domain = domain;
6078
6079         char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
6080         if (mono_error_set_pending_exception (&error))
6081                 return;
6082         image = create_dynamic_mono_image (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
6083         image->initial_image = TRUE;
6084         assembly->assembly.aname.name = image->image.name;
6085         assembly->assembly.image = &image->image;
6086         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
6087                 /* -1 to correct for the trailing NULL byte */
6088                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
6089                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6090                 }
6091                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
6092         }
6093
6094         mono_domain_assemblies_lock (domain);
6095         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6096         mono_domain_assemblies_unlock (domain);
6097
6098         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6099         
6100         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6101         
6102         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6103 }
6104
6105 #endif /* !DISABLE_REFLECTION_EMIT */
6106
6107 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6108
6109 static int
6110 calc_section_size (MonoDynamicImage *assembly)
6111 {
6112         int nsections = 0;
6113
6114         /* alignment constraints */
6115         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6116         g_assert ((assembly->code.index % 4) == 0);
6117         assembly->meta_size += 3;
6118         assembly->meta_size &= ~3;
6119         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6120         g_assert ((assembly->resources.index % 4) == 0);
6121
6122         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6123         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6124         nsections++;
6125
6126         if (assembly->win32_res) {
6127                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6128
6129                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6130                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6131                 nsections++;
6132         }
6133
6134         assembly->sections [MONO_SECTION_RELOC].size = 12;
6135         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6136         nsections++;
6137
6138         return nsections;
6139 }
6140
6141 typedef struct {
6142         guint32 id;
6143         guint32 offset;
6144         GSList *children;
6145         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6146 } ResTreeNode;
6147
6148 static int
6149 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6150 {
6151         ResTreeNode *t1 = (ResTreeNode*)a;
6152         ResTreeNode *t2 = (ResTreeNode*)b;
6153
6154         return t1->id - t2->id;
6155 }
6156
6157 /*
6158  * resource_tree_create:
6159  *
6160  *  Organize the resources into a resource tree.
6161  */
6162 static ResTreeNode *
6163 resource_tree_create (MonoArray *win32_resources)
6164 {
6165         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6166         GSList *l;
6167         int i;
6168
6169         tree = g_new0 (ResTreeNode, 1);
6170         
6171         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6172                 MonoReflectionWin32Resource *win32_res =
6173                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6174
6175                 /* Create node */
6176
6177                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6178                 lang_node = g_new0 (ResTreeNode, 1);
6179                 lang_node->id = win32_res->lang_id;
6180                 lang_node->win32_res = win32_res;
6181
6182                 /* Create type node if neccesary */
6183                 type_node = NULL;
6184                 for (l = tree->children; l; l = l->next)
6185                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6186                                 type_node = (ResTreeNode*)l->data;
6187                                 break;
6188                         }
6189
6190                 if (!type_node) {
6191                         type_node = g_new0 (ResTreeNode, 1);
6192                         type_node->id = win32_res->res_type;
6193
6194                         /* 
6195                          * The resource types have to be sorted otherwise
6196                          * Windows Explorer can't display the version information.
6197                          */
6198                         tree->children = g_slist_insert_sorted (tree->children, 
6199                                 type_node, resource_tree_compare_by_id);
6200                 }
6201
6202                 /* Create res node if neccesary */
6203                 res_node = NULL;
6204                 for (l = type_node->children; l; l = l->next)
6205                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6206                                 res_node = (ResTreeNode*)l->data;
6207                                 break;
6208                         }
6209
6210                 if (!res_node) {
6211                         res_node = g_new0 (ResTreeNode, 1);
6212                         res_node->id = win32_res->res_id;
6213                         type_node->children = g_slist_append (type_node->children, res_node);
6214                 }
6215
6216                 res_node->children = g_slist_append (res_node->children, lang_node);
6217         }
6218
6219         return tree;
6220 }
6221
6222 /*
6223  * resource_tree_encode:
6224  * 
6225  *   Encode the resource tree into the format used in the PE file.
6226  */
6227 static void
6228 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6229 {
6230         char *entries;
6231         MonoPEResourceDir dir;
6232         MonoPEResourceDirEntry dir_entry;
6233         MonoPEResourceDataEntry data_entry;
6234         GSList *l;
6235         guint32 res_id_entries;
6236
6237         /*
6238          * For the format of the resource directory, see the article
6239          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6240          * Matt Pietrek
6241          */
6242
6243         memset (&dir, 0, sizeof (dir));
6244         memset (&dir_entry, 0, sizeof (dir_entry));
6245         memset (&data_entry, 0, sizeof (data_entry));
6246
6247         g_assert (sizeof (dir) == 16);
6248         g_assert (sizeof (dir_entry) == 8);
6249         g_assert (sizeof (data_entry) == 16);
6250
6251         node->offset = p - begin;
6252
6253         /* IMAGE_RESOURCE_DIRECTORY */
6254         res_id_entries = g_slist_length (node->children);
6255         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6256
6257         memcpy (p, &dir, sizeof (dir));
6258         p += sizeof (dir);
6259
6260         /* Reserve space for entries */
6261         entries = p;
6262         p += sizeof (dir_entry) * res_id_entries;
6263
6264         /* Write children */
6265         for (l = node->children; l; l = l->next) {
6266                 ResTreeNode *child = (ResTreeNode*)l->data;
6267
6268                 if (child->win32_res) {
6269                         guint32 size;
6270
6271                         child->offset = p - begin;
6272
6273                         /* IMAGE_RESOURCE_DATA_ENTRY */
6274                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6275                         size = mono_array_length (child->win32_res->res_data);
6276                         data_entry.rde_size = GUINT32_TO_LE (size);
6277
6278                         memcpy (p, &data_entry, sizeof (data_entry));
6279                         p += sizeof (data_entry);
6280
6281                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6282                         p += size;
6283                 } else {
6284                         resource_tree_encode (child, begin, p, &p);
6285                 }
6286         }
6287
6288         /* IMAGE_RESOURCE_ENTRY */
6289         for (l = node->children; l; l = l->next) {
6290                 ResTreeNode *child = (ResTreeNode*)l->data;
6291
6292                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6293                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6294
6295                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6296                 entries += sizeof (dir_entry);
6297         }
6298
6299         *endbuf = p;
6300 }
6301
6302 static void
6303 resource_tree_free (ResTreeNode * node)
6304 {
6305         GSList * list;
6306         for (list = node->children; list; list = list->next)
6307                 resource_tree_free ((ResTreeNode*)list->data);
6308         g_slist_free(node->children);
6309         g_free (node);
6310 }
6311
6312 static void
6313 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6314 {
6315         char *buf;
6316         char *p;
6317         guint32 size, i;
6318         MonoReflectionWin32Resource *win32_res;
6319         ResTreeNode *tree;
6320
6321         if (!assemblyb->win32_resources)
6322                 return;
6323
6324         /*
6325          * Resources are stored in a three level tree inside the PE file.
6326          * - level one contains a node for each type of resource
6327          * - level two contains a node for each resource
6328          * - level three contains a node for each instance of a resource for a
6329          *   specific language.
6330          */
6331
6332         tree = resource_tree_create (assemblyb->win32_resources);
6333
6334         /* Estimate the size of the encoded tree */
6335         size = 0;
6336         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6337                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6338                 size += mono_array_length (win32_res->res_data);
6339         }
6340         /* Directory structure */
6341         size += mono_array_length (assemblyb->win32_resources) * 256;
6342         p = buf = (char *)g_malloc (size);
6343
6344         resource_tree_encode (tree, p, p, &p);
6345
6346         g_assert (p - buf <= size);
6347
6348         assembly->win32_res = (char *)g_malloc (p - buf);
6349         assembly->win32_res_size = p - buf;
6350         memcpy (assembly->win32_res, buf, p - buf);
6351
6352         g_free (buf);
6353         resource_tree_free (tree);
6354 }
6355
6356 static void
6357 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6358 {
6359         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6360         int i;
6361
6362         p += sizeof (MonoPEResourceDir);
6363         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6364                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6365                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6366                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6367                         fixup_resource_directory (res_section, child, rva);
6368                 } else {
6369                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6370                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6371                 }
6372
6373                 p += sizeof (MonoPEResourceDirEntry);
6374         }
6375 }
6376
6377 static void
6378 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6379 {
6380         guint32 dummy;
6381         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6382                 g_error ("WriteFile returned %d\n", GetLastError ());
6383 }
6384
6385 /*
6386  * mono_image_create_pefile:
6387  * @mb: a module builder object
6388  * 
6389  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6390  * assembly->pefile where it can be easily retrieved later in chunks.
6391  */
6392 gboolean
6393 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6394 {
6395         MonoMSDOSHeader *msdos;
6396         MonoDotNetHeader *header;
6397         MonoSectionTable *section;
6398         MonoCLIHeader *cli_header;
6399         guint32 size, image_size, virtual_base, text_offset;
6400         guint32 header_start, section_start, file_offset, virtual_offset;
6401         MonoDynamicImage *assembly;
6402         MonoReflectionAssemblyBuilder *assemblyb;
6403         MonoDynamicStream pefile_stream = {0};
6404         MonoDynamicStream *pefile = &pefile_stream;
6405         int i, nsections;
6406         guint32 *rva, value;
6407         guchar *p;
6408         static const unsigned char msheader[] = {
6409                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6410                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6411                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6412                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6413                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6414                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6415                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6416                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6417         };
6418
6419         mono_error_init (error);
6420
6421         assemblyb = mb->assemblyb;
6422
6423         mono_image_basic_init (assemblyb);
6424         assembly = mb->dynamic_image;
6425
6426         assembly->pe_kind = assemblyb->pe_kind;
6427         assembly->machine = assemblyb->machine;
6428         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6429         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6430         
6431         if (!mono_image_build_metadata (mb, error))
6432                 return FALSE;
6433         
6434
6435         if (mb->is_main && assemblyb->resources) {
6436                 int len = mono_array_length (assemblyb->resources);
6437                 for (i = 0; i < len; ++i) {
6438                         if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
6439                                 return FALSE;
6440                 }
6441         }
6442
6443         if (mb->resources) {
6444                 int len = mono_array_length (mb->resources);
6445                 for (i = 0; i < len; ++i) {
6446                         if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
6447                                 return FALSE;
6448                 }
6449         }
6450
6451         if (!build_compressed_metadata (assembly, error))
6452                 return FALSE;
6453
6454         if (mb->is_main)
6455                 assembly_add_win32_resources (assembly, assemblyb);
6456
6457         nsections = calc_section_size (assembly);
6458         
6459         /* The DOS header and stub */
6460         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6461         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6462
6463         /* the dotnet header */
6464         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6465
6466         /* the section tables */
6467         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6468
6469         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6470         virtual_offset = VIRT_ALIGN;
6471         image_size = 0;
6472
6473         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6474                 if (!assembly->sections [i].size)
6475                         continue;
6476                 /* align offsets */
6477                 file_offset += FILE_ALIGN - 1;
6478                 file_offset &= ~(FILE_ALIGN - 1);
6479                 virtual_offset += VIRT_ALIGN - 1;
6480                 virtual_offset &= ~(VIRT_ALIGN - 1);
6481
6482                 assembly->sections [i].offset = file_offset;
6483                 assembly->sections [i].rva = virtual_offset;
6484
6485                 file_offset += assembly->sections [i].size;
6486                 virtual_offset += assembly->sections [i].size;
6487                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6488         }
6489
6490         file_offset += FILE_ALIGN - 1;
6491         file_offset &= ~(FILE_ALIGN - 1);
6492
6493         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6494
6495         /* back-patch info */
6496         msdos = (MonoMSDOSHeader*)pefile->data;
6497         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6498
6499         header = (MonoDotNetHeader*)(pefile->data + header_start);
6500         header->pesig [0] = 'P';
6501         header->pesig [1] = 'E';
6502         
6503         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6504         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6505         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6506         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6507         if (assemblyb->pekind == 1) {
6508                 /* it's a dll */
6509                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6510         } else {
6511                 /* it's an exe */
6512                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6513         }
6514
6515         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6516
6517         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6518         header->pe.pe_major = 6;
6519         header->pe.pe_minor = 0;
6520         size = assembly->sections [MONO_SECTION_TEXT].size;
6521         size += FILE_ALIGN - 1;
6522         size &= ~(FILE_ALIGN - 1);
6523         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6524         size = assembly->sections [MONO_SECTION_RSRC].size;
6525         size += FILE_ALIGN - 1;
6526         size &= ~(FILE_ALIGN - 1);
6527         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6528         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6529         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6530         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6531         /* pe_rva_entry_point always at the beginning of the text section */
6532         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6533
6534         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6535         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6536         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6537         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6538         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6539         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6540         size = section_start;
6541         size += FILE_ALIGN - 1;
6542         size &= ~(FILE_ALIGN - 1);
6543         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6544         size = image_size;
6545         size += VIRT_ALIGN - 1;
6546         size &= ~(VIRT_ALIGN - 1);
6547         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6548
6549         /*
6550         // Translate the PEFileKind value to the value expected by the Windows loader
6551         */
6552         {
6553                 short kind;
6554
6555                 /*
6556                 // PEFileKinds.Dll == 1
6557                 // PEFileKinds.ConsoleApplication == 2
6558                 // PEFileKinds.WindowApplication == 3
6559                 //
6560                 // need to get:
6561                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6562                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6563                 */
6564                 if (assemblyb->pekind == 3)
6565                         kind = 2;
6566                 else
6567                         kind = 3;
6568                 
6569                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6570         }    
6571         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6572         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6573         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6574         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6575         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6576         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6577
6578         /* fill data directory entries */
6579
6580         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6581         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6582
6583         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6584         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6585
6586         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6587         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6588         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6589         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6590         /* patch entrypoint name */
6591         if (assemblyb->pekind == 1)
6592                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6593         else
6594                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6595         /* patch imported function RVA name */
6596         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6597         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6598
6599         /* the import table */
6600         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6601         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6602         /* patch imported dll RVA name and other entries in the dir */
6603         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6604         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6605         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6606         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6607         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6608         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6609
6610         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6611         value = (assembly->text_rva + assembly->imp_names_offset);
6612         *p++ = (value) & 0xff;
6613         *p++ = (value >> 8) & (0xff);
6614         *p++ = (value >> 16) & (0xff);
6615         *p++ = (value >> 24) & (0xff);
6616
6617         /* the CLI header info */
6618         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6619         cli_header->ch_size = GUINT32_FROM_LE (72);
6620         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6621         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6622         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6623         if (assemblyb->entry_point) {
6624                 guint32 table_idx = 0;
6625                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6626                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6627                         table_idx = methodb->table_idx;
6628                 } else {
6629                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6630                 }
6631                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6632         } else {
6633                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6634         }
6635         /* The embedded managed resources */
6636         text_offset = assembly->text_rva + assembly->code.index;
6637         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6638         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6639         text_offset += assembly->resources.index;
6640         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6641         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6642         text_offset += assembly->meta_size;
6643         if (assembly->strong_name_size) {
6644                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6645                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6646                 text_offset += assembly->strong_name_size;
6647         }
6648
6649         /* write the section tables and section content */
6650         section = (MonoSectionTable*)(pefile->data + section_start);
6651         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6652                 static const char section_names [][7] = {
6653                         ".text", ".rsrc", ".reloc"
6654                 };
6655                 if (!assembly->sections [i].size)
6656                         continue;
6657                 strcpy (section->st_name, section_names [i]);
6658                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6659                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6660                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6661                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6662                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6663                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6664                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6665                 section ++;
6666         }
6667         
6668         checked_write_file (file, pefile->data, pefile->index);
6669         
6670         mono_dynamic_stream_reset (pefile);
6671         
6672         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6673                 if (!assembly->sections [i].size)
6674                         continue;
6675                 
6676                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6677                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6678                 
6679                 switch (i) {
6680                 case MONO_SECTION_TEXT:
6681                         /* patch entry point */
6682                         p = (guchar*)(assembly->code.data + 2);
6683                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6684                         *p++ = (value) & 0xff;
6685                         *p++ = (value >> 8) & 0xff;
6686                         *p++ = (value >> 16) & 0xff;
6687                         *p++ = (value >> 24) & 0xff;
6688                 
6689                         checked_write_file (file, assembly->code.data, assembly->code.index);
6690                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6691                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6692                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6693                                 
6694
6695                         g_free (assembly->image.raw_metadata);
6696                         break;
6697                 case MONO_SECTION_RELOC: {
6698                         struct {
6699                                 guint32 page_rva;
6700                                 guint32 block_size;
6701                                 guint16 type_and_offset;
6702                                 guint16 term;
6703                         } reloc;
6704                         
6705                         g_assert (sizeof (reloc) == 12);
6706                         
6707                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6708                         reloc.block_size = GUINT32_FROM_LE (12);
6709                         
6710                         /* 
6711                          * the entrypoint is always at the start of the text section 
6712                          * 3 is IMAGE_REL_BASED_HIGHLOW
6713                          * 2 is patch_size_rva - text_rva
6714                          */
6715                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6716                         reloc.term = 0;
6717                         
6718                         checked_write_file (file, &reloc, sizeof (reloc));
6719                         
6720                         break;
6721                 }
6722                 case MONO_SECTION_RSRC:
6723                         if (assembly->win32_res) {
6724
6725                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6726                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6727                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6728                         }
6729                         break;
6730                 default:
6731                         g_assert_not_reached ();
6732                 }
6733         }
6734         
6735         /* check that the file is properly padded */
6736         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6737                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6738         if (! SetEndOfFile (file))
6739                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6740         
6741         mono_dynamic_stream_reset (&assembly->code);
6742         mono_dynamic_stream_reset (&assembly->us);
6743         mono_dynamic_stream_reset (&assembly->blob);
6744         mono_dynamic_stream_reset (&assembly->guid);
6745         mono_dynamic_stream_reset (&assembly->sheap);
6746
6747         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6748         g_hash_table_destroy (assembly->blob_cache);
6749         assembly->blob_cache = NULL;
6750
6751         return TRUE;
6752 }
6753
6754 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6755
6756 gboolean
6757 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6758 {
6759         g_assert_not_reached ();
6760 }
6761
6762 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6763
6764 #ifndef DISABLE_REFLECTION_EMIT
6765
6766 MonoReflectionModule *
6767 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6768 {
6769         char *name;
6770         MonoImage *image;
6771         MonoImageOpenStatus status;
6772         MonoDynamicAssembly *assembly;
6773         guint32 module_count;
6774         MonoImage **new_modules;
6775         gboolean *new_modules_loaded;
6776         
6777         mono_error_init (error);
6778         
6779         name = mono_string_to_utf8_checked (fileName, error);
6780         return_val_if_nok (error, NULL);
6781
6782         image = mono_image_open (name, &status);
6783         if (!image) {
6784                 if (status == MONO_IMAGE_ERROR_ERRNO)
6785                         mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6786                 else
6787                         mono_error_set_bad_image_name (error, name, NULL);
6788                 g_free (name);
6789                 return NULL;
6790         }
6791
6792         g_free (name);
6793
6794         assembly = ab->dynamic_assembly;
6795         image->assembly = (MonoAssembly*)assembly;
6796
6797         module_count = image->assembly->image->module_count;
6798         new_modules = g_new0 (MonoImage *, module_count + 1);
6799         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6800
6801         if (image->assembly->image->modules)
6802                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6803         if (image->assembly->image->modules_loaded)
6804                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6805         new_modules [module_count] = image;
6806         new_modules_loaded [module_count] = TRUE;
6807         mono_image_addref (image);
6808
6809         g_free (image->assembly->image->modules);
6810         image->assembly->image->modules = new_modules;
6811         image->assembly->image->modules_loaded = new_modules_loaded;
6812         image->assembly->image->module_count ++;
6813
6814         mono_assembly_load_references (image, &status);
6815         if (status) {
6816                 mono_image_close (image);
6817                 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6818                 return NULL;
6819         }
6820
6821         return mono_module_get_object_checked (mono_domain_get (), image, error);
6822 }
6823
6824 #endif /* DISABLE_REFLECTION_EMIT */
6825
6826 /*
6827  * We need to return always the same object for MethodInfo, FieldInfo etc..
6828  * but we need to consider the reflected type.
6829  * type uses a different hash, since it uses custom hash/equal functions.
6830  */
6831
6832 typedef struct {
6833         gpointer item;
6834         MonoClass *refclass;
6835 } ReflectedEntry;
6836
6837 static gboolean
6838 reflected_equal (gconstpointer a, gconstpointer b) {
6839         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6840         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6841
6842         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6843 }
6844
6845 static guint
6846 reflected_hash (gconstpointer a) {
6847         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6848         return mono_aligned_addr_hash (ea->item);
6849 }
6850
6851 #define CHECK_OBJECT(t,p,k)     \
6852         do {    \
6853                 t _obj; \
6854                 ReflectedEntry e;       \
6855                 e.item = (p);   \
6856                 e.refclass = (k);       \
6857                 mono_domain_lock (domain);      \
6858                 if (!domain->refobject_hash)    \
6859                         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");  \
6860                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6861                         mono_domain_unlock (domain);    \
6862                         return _obj;    \
6863                 }       \
6864         mono_domain_unlock (domain); \
6865         } while (0)
6866
6867 #ifdef HAVE_BOEHM_GC
6868 /* ReflectedEntry doesn't need to be GC tracked */
6869 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6870 #define FREE_REFENTRY(entry) g_free ((entry))
6871 #define REFENTRY_REQUIRES_CLEANUP
6872 #else
6873 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6874 /* FIXME: */
6875 #define FREE_REFENTRY(entry)
6876 #endif
6877
6878 #define CACHE_OBJECT(t,p,o,k)   \
6879         do {    \
6880                 t _obj; \
6881         ReflectedEntry pe; \
6882         pe.item = (p); \
6883         pe.refclass = (k); \
6884         mono_domain_lock (domain); \
6885                 if (!domain->refobject_hash)    \
6886                         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");  \
6887         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6888         if (!_obj) { \
6889                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6890                     e->item = (p);      \
6891                     e->refclass = (k);  \
6892                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6893             _obj = o; \
6894         } \
6895                 mono_domain_unlock (domain);    \
6896         return _obj; \
6897         } while (0)
6898
6899 static void
6900 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6901 {
6902         mono_domain_lock (domain);
6903         if (domain->refobject_hash) {
6904         ReflectedEntry pe;
6905                 gpointer orig_pe, orig_value;
6906
6907                 pe.item = o;
6908                 pe.refclass = klass;
6909                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6910                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6911                         FREE_REFENTRY (orig_pe);
6912                 }
6913         }
6914         mono_domain_unlock (domain);
6915 }
6916
6917 #ifdef REFENTRY_REQUIRES_CLEANUP
6918 static void
6919 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6920 {
6921         FREE_REFENTRY (key);
6922 }
6923 #endif
6924
6925 void
6926 mono_reflection_cleanup_domain (MonoDomain *domain)
6927 {
6928         if (domain->refobject_hash) {
6929 /*let's avoid scanning the whole hashtable if not needed*/
6930 #ifdef REFENTRY_REQUIRES_CLEANUP
6931                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6932 #endif
6933                 mono_g_hash_table_destroy (domain->refobject_hash);
6934                 domain->refobject_hash = NULL;
6935         }
6936 }
6937
6938 #ifndef DISABLE_REFLECTION_EMIT
6939 static gpointer
6940 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6941 {
6942         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6943 }
6944
6945 static gpointer
6946 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6947 {
6948         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6949 }
6950
6951 static gboolean
6952 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
6953 {
6954         MonoDynamicImage *image = moduleb->dynamic_image;
6955         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6956         mono_error_init (error);
6957         if (!image) {
6958                 int module_count;
6959                 MonoImage **new_modules;
6960                 MonoImage *ass;
6961                 char *name, *fqname;
6962                 /*
6963                  * FIXME: we already created an image in mono_image_basic_init (), but
6964                  * we don't know which module it belongs to, since that is only 
6965                  * determined at assembly save time.
6966                  */
6967                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6968                 name = mono_string_to_utf8_checked (ab->name, error);
6969                 return_val_if_nok (error, FALSE);
6970                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
6971                 if (!is_ok (error)) {
6972                         g_free (name);
6973                         return FALSE;
6974                 }
6975                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6976
6977                 moduleb->module.image = &image->image;
6978                 moduleb->dynamic_image = image;
6979                 register_module (mono_object_domain (moduleb), moduleb, image);
6980
6981                 /* register the module with the assembly */
6982                 ass = ab->dynamic_assembly->assembly.image;
6983                 module_count = ass->module_count;
6984                 new_modules = g_new0 (MonoImage *, module_count + 1);
6985
6986                 if (ass->modules)
6987                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6988                 new_modules [module_count] = &image->image;
6989                 mono_image_addref (&image->image);
6990
6991                 g_free (ass->modules);
6992                 ass->modules = new_modules;
6993                 ass->module_count ++;
6994         }
6995         return TRUE;
6996 }
6997
6998 void
6999 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
7000 {
7001         MonoError error;
7002         (void) image_module_basic_init (moduleb, &error);
7003         mono_error_set_pending_exception (&error);
7004 }
7005
7006 void
7007 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
7008 {
7009         MonoDynamicImage *image = moduleb->dynamic_image;
7010
7011         g_assert (type->type);
7012         image->wrappers_type = mono_class_from_mono_type (type->type);
7013 }
7014
7015 #endif
7016
7017 /*
7018  * mono_assembly_get_object:
7019  * @domain: an app domain
7020  * @assembly: an assembly
7021  *
7022  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
7023  */
7024 MonoReflectionAssembly*
7025 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
7026 {
7027         MonoError error;
7028         MonoReflectionAssembly *result;
7029         result = mono_assembly_get_object_checked (domain, assembly, &error);
7030         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7031         return result;
7032 }
7033 /*
7034  * mono_assembly_get_object_checked:
7035  * @domain: an app domain
7036  * @assembly: an assembly
7037  *
7038  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
7039  */
7040 MonoReflectionAssembly*
7041 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
7042 {
7043         MonoReflectionAssembly *res;
7044         
7045         mono_error_init (error);
7046
7047         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
7048         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
7049         if (!res)
7050                 return NULL;
7051         res->assembly = assembly;
7052
7053         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
7054 }
7055
7056
7057
7058 MonoReflectionModule*   
7059 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
7060 {
7061         MonoError error;
7062         MonoReflectionModule *result;
7063         result = mono_module_get_object_checked (domain, image, &error);
7064         mono_error_cleanup (&error);
7065         return result;
7066 }
7067
7068 MonoReflectionModule*
7069 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
7070 {
7071         MonoReflectionModule *res;
7072         char* basename;
7073         
7074         mono_error_init (error);
7075         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
7076         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7077         if (!res)
7078                 return NULL;
7079
7080         res->image = image;
7081         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7082         if (!assm_obj)
7083                 return NULL;
7084         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7085
7086         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
7087         basename = g_path_get_basename (image->name);
7088         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
7089         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
7090         
7091         g_free (basename);
7092
7093         if (image->assembly->image == image) {
7094                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
7095         } else {
7096                 int i;
7097                 res->token = 0;
7098                 if (image->assembly->image->modules) {
7099                         for (i = 0; i < image->assembly->image->module_count; i++) {
7100                                 if (image->assembly->image->modules [i] == image)
7101                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
7102                         }
7103                         g_assert (res->token);
7104                 }
7105         }
7106
7107         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7108 }
7109
7110 MonoReflectionModule*
7111 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7112 {
7113         MonoError error;
7114         MonoReflectionModule *result;
7115         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7116         mono_error_cleanup (&error);
7117         return result;
7118 }
7119
7120 MonoReflectionModule*
7121 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7122 {
7123         MonoReflectionModule *res;
7124         MonoTableInfo *table;
7125         guint32 cols [MONO_FILE_SIZE];
7126         const char *name;
7127         guint32 i, name_idx;
7128         const char *val;
7129         
7130         mono_error_init (error);
7131
7132         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7133         if (!res)
7134                 return NULL;
7135
7136         table = &image->tables [MONO_TABLE_FILE];
7137         g_assert (table_index < table->rows);
7138         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7139
7140         res->image = NULL;
7141         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7142         if (!assm_obj)
7143                 return NULL;
7144         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7145         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7146
7147         /* Check whenever the row has a corresponding row in the moduleref table */
7148         table = &image->tables [MONO_TABLE_MODULEREF];
7149         for (i = 0; i < table->rows; ++i) {
7150                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7151                 val = mono_metadata_string_heap (image, name_idx);
7152                 if (strcmp (val, name) == 0)
7153                         res->image = image->modules [i];
7154         }
7155
7156         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7157         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7158         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7159         res->is_resource = cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA;
7160         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7161
7162         return res;
7163 }
7164
7165 static gboolean
7166 verify_safe_for_managed_space (MonoType *type)
7167 {
7168         switch (type->type) {
7169 #ifdef DEBUG_HARDER
7170         case MONO_TYPE_ARRAY:
7171                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7172         case MONO_TYPE_PTR:
7173                 return verify_safe_for_managed_space (type->data.type);
7174         case MONO_TYPE_SZARRAY:
7175                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7176         case MONO_TYPE_GENERICINST: {
7177                 MonoGenericInst *inst = type->data.generic_class->inst;
7178                 int i;
7179                 if (!inst->is_open)
7180                         break;
7181                 for (i = 0; i < inst->type_argc; ++i)
7182                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7183                                 return FALSE;
7184                 return TRUE;
7185         }
7186 #endif
7187         case MONO_TYPE_VAR:
7188         case MONO_TYPE_MVAR:
7189                 return TRUE;
7190         default:
7191                 return TRUE;
7192         }
7193 }
7194
7195 static MonoType*
7196 mono_type_normalize (MonoType *type)
7197 {
7198         int i;
7199         MonoGenericClass *gclass;
7200         MonoGenericInst *ginst;
7201         MonoClass *gtd;
7202         MonoGenericContainer *gcontainer;
7203         MonoType **argv = NULL;
7204         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7205
7206         if (type->type != MONO_TYPE_GENERICINST)
7207                 return type;
7208
7209         gclass = type->data.generic_class;
7210         ginst = gclass->context.class_inst;
7211         if (!ginst->is_open)
7212                 return type;
7213
7214         gtd = gclass->container_class;
7215         gcontainer = gtd->generic_container;
7216         argv = g_newa (MonoType*, ginst->type_argc);
7217
7218         for (i = 0; i < ginst->type_argc; ++i) {
7219                 MonoType *t = ginst->type_argv [i], *norm;
7220                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7221                         is_denorm_gtd = FALSE;
7222                 norm = mono_type_normalize (t);
7223                 argv [i] = norm;
7224                 if (norm != t)
7225                         requires_rebind = TRUE;
7226         }
7227
7228         if (is_denorm_gtd)
7229                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7230
7231         if (requires_rebind) {
7232                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7233                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7234         }
7235
7236         return type;
7237 }
7238 /*
7239  * mono_type_get_object:
7240  * @domain: an app domain
7241  * @type: a type
7242  *
7243  * Return an System.MonoType object representing the type @type.
7244  */
7245 MonoReflectionType*
7246 mono_type_get_object (MonoDomain *domain, MonoType *type)
7247 {
7248         MonoError error;
7249         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7250         mono_error_cleanup (&error);
7251
7252         return ret;
7253 }
7254
7255 MonoReflectionType*
7256 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7257 {
7258         MonoType *norm_type;
7259         MonoReflectionType *res;
7260         MonoClass *klass;
7261
7262         mono_error_init (error);
7263
7264         klass = mono_class_from_mono_type (type);
7265
7266         /*we must avoid using @type as it might have come
7267          * from a mono_metadata_type_dup and the caller
7268          * expects that is can be freed.
7269          * Using the right type from 
7270          */
7271         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7272
7273         /* void is very common */
7274         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7275                 return (MonoReflectionType*)domain->typeof_void;
7276
7277         /*
7278          * If the vtable of the given class was already created, we can use
7279          * the MonoType from there and avoid all locking and hash table lookups.
7280          * 
7281          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7282          * that the resulting object is different.   
7283          */
7284         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7285                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7286                 if (vtable && vtable->type)
7287                         return (MonoReflectionType *)vtable->type;
7288         }
7289
7290         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7291         mono_domain_lock (domain);
7292         if (!domain->type_hash)
7293                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7294                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7295         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7296                 mono_domain_unlock (domain);
7297                 mono_loader_unlock ();
7298                 return res;
7299         }
7300
7301         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7302          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7303          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7304          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7305          * artifact of how generics are encoded and should be transparent to managed code so we
7306          * need to weed out this diference when retrieving managed System.Type objects.
7307          */
7308         norm_type = mono_type_normalize (type);
7309         if (norm_type != type) {
7310                 res = mono_type_get_object_checked (domain, norm_type, error);
7311                 if (!mono_error_ok (error))
7312                         return NULL;
7313                 mono_g_hash_table_insert (domain->type_hash, type, res);
7314                 mono_domain_unlock (domain);
7315                 mono_loader_unlock ();
7316                 return res;
7317         }
7318
7319         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7320         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7321                 g_assert (0);
7322
7323         if (!verify_safe_for_managed_space (type)) {
7324                 mono_domain_unlock (domain);
7325                 mono_loader_unlock ();
7326                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7327                 return NULL;
7328         }
7329
7330         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7331                 gboolean is_type_done = TRUE;
7332                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7333                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7334                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7335                 */
7336                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7337                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7338
7339                         if (gparam->owner && gparam->owner->is_method) {
7340                                 MonoMethod *method = gparam->owner->owner.method;
7341                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7342                                         is_type_done = FALSE;
7343                         } else if (gparam->owner && !gparam->owner->is_method) {
7344                                 MonoClass *klass = gparam->owner->owner.klass;
7345                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7346                                         is_type_done = FALSE;
7347                         }
7348                 } 
7349
7350                 /* g_assert_not_reached (); */
7351                 /* should this be considered an error condition? */
7352                 if (is_type_done && !type->byref) {
7353                         mono_domain_unlock (domain);
7354                         mono_loader_unlock ();
7355                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7356                 }
7357         }
7358         /* This is stored in vtables/JITted code so it has to be pinned */
7359         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
7360         if (!mono_error_ok (error))
7361                 return NULL;
7362
7363         res->type = type;
7364         mono_g_hash_table_insert (domain->type_hash, type, res);
7365
7366         if (type->type == MONO_TYPE_VOID)
7367                 domain->typeof_void = (MonoObject*)res;
7368
7369         mono_domain_unlock (domain);
7370         mono_loader_unlock ();
7371         return res;
7372 }
7373
7374 /*
7375  * mono_method_get_object:
7376  * @domain: an app domain
7377  * @method: a method
7378  * @refclass: the reflected type (can be NULL)
7379  *
7380  * Return an System.Reflection.MonoMethod object representing the method @method.
7381  */
7382 MonoReflectionMethod*
7383 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7384 {
7385         MonoError error;
7386         MonoReflectionMethod *ret = NULL;
7387         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7388         mono_error_cleanup (&error);
7389         return ret;
7390 }
7391
7392 /*
7393  * mono_method_get_object_checked:
7394  * @domain: an app domain
7395  * @method: a method
7396  * @refclass: the reflected type (can be NULL)
7397  * @error: set on error.
7398  *
7399  * Return an System.Reflection.MonoMethod object representing the method @method.
7400  * Returns NULL and sets @error on error.
7401  */
7402 MonoReflectionMethod*
7403 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7404 {
7405         /*
7406          * We use the same C representation for methods and constructors, but the type 
7407          * name in C# is different.
7408          */
7409         MonoReflectionType *rt;
7410         MonoClass *klass;
7411         MonoReflectionMethod *ret;
7412
7413         mono_error_init (error);
7414
7415         if (method->is_inflated) {
7416                 MonoReflectionGenericMethod *gret;
7417
7418                 if (!refclass)
7419                         refclass = method->klass;
7420                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7421                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7422                         klass = mono_class_get_mono_generic_cmethod_class ();
7423                 } else {
7424                         klass = mono_class_get_mono_generic_method_class ();
7425                 }
7426                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7427                 if (!mono_error_ok (error))
7428                         goto leave;
7429                 gret->method.method = method;
7430
7431                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7432
7433                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7434                 if (!mono_error_ok (error))
7435                     goto leave;
7436
7437                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7438
7439                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7440         }
7441
7442         if (!refclass)
7443                 refclass = method->klass;
7444
7445         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7446         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7447                 klass = mono_class_get_mono_cmethod_class ();
7448         }
7449         else {
7450                 klass = mono_class_get_mono_method_class ();
7451         }
7452         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7453         if (!mono_error_ok (error))
7454                 goto leave;
7455         ret->method = method;
7456
7457         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7458         if (!mono_error_ok (error))
7459                 goto leave;
7460
7461         MONO_OBJECT_SETREF (ret, reftype, rt);
7462
7463         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7464
7465 leave:
7466         g_assert (!mono_error_ok (error));
7467         return NULL;
7468 }
7469
7470 /*
7471  * mono_method_clear_object:
7472  *
7473  *   Clear the cached reflection objects for the dynamic method METHOD.
7474  */
7475 void
7476 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7477 {
7478         MonoClass *klass;
7479         g_assert (method_is_dynamic (method));
7480
7481         klass = method->klass;
7482         while (klass) {
7483                 clear_cached_object (domain, method, klass);
7484                 klass = klass->parent;
7485         }
7486         /* Added by mono_param_get_objects () */
7487         clear_cached_object (domain, &(method->signature), NULL);
7488         klass = method->klass;
7489         while (klass) {
7490                 clear_cached_object (domain, &(method->signature), klass);
7491                 klass = klass->parent;
7492         }
7493 }
7494
7495 /*
7496  * mono_field_get_object:
7497  * @domain: an app domain
7498  * @klass: a type
7499  * @field: a field
7500  *
7501  * Return an System.Reflection.MonoField object representing the field @field
7502  * in class @klass.
7503  */
7504 MonoReflectionField*
7505 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7506 {
7507         MonoError error;
7508         MonoReflectionField *result;
7509         result = mono_field_get_object_checked (domain, klass, field, &error);
7510         mono_error_cleanup (&error);
7511         return result;
7512 }
7513
7514 /*
7515  * mono_field_get_object_checked:
7516  * @domain: an app domain
7517  * @klass: a type
7518  * @field: a field
7519  * @error: set on error
7520  *
7521  * Return an System.Reflection.MonoField object representing the field @field
7522  * in class @klass. On error, returns NULL and sets @error.
7523  */
7524 MonoReflectionField*
7525 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7526 {
7527         MonoReflectionType *rt;
7528         MonoReflectionField *res;
7529
7530         mono_error_init (error);
7531
7532         CHECK_OBJECT (MonoReflectionField *, field, klass);
7533         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7534         if (!res)
7535                 return NULL;
7536         res->klass = klass;
7537         res->field = field;
7538         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7539
7540         if (is_field_on_inst (field)) {
7541                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7542
7543                 rt = mono_type_get_object_checked (domain, field->type, error);
7544                 if (!mono_error_ok (error))
7545                         return NULL;
7546
7547                 MONO_OBJECT_SETREF (res, type, rt);
7548         } else {
7549                 if (field->type) {
7550                         rt = mono_type_get_object_checked (domain, field->type, error);
7551                         if (!mono_error_ok (error))
7552                                 return NULL;
7553
7554                         MONO_OBJECT_SETREF (res, type, rt);
7555                 }
7556                 res->attrs = mono_field_get_flags (field);
7557         }
7558         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7559 }
7560
7561 /*
7562  * mono_property_get_object:
7563  * @domain: an app domain
7564  * @klass: a type
7565  * @property: a property
7566  *
7567  * Return an System.Reflection.MonoProperty object representing the property @property
7568  * in class @klass.
7569  */
7570 MonoReflectionProperty*
7571 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7572 {
7573         MonoError error;
7574         MonoReflectionProperty *result;
7575         result = mono_property_get_object_checked (domain, klass, property, &error);
7576         mono_error_cleanup (&error);
7577         return result;
7578 }
7579
7580 /**
7581  * mono_property_get_object:
7582  * @domain: an app domain
7583  * @klass: a type
7584  * @property: a property
7585  * @error: set on error
7586  *
7587  * Return an System.Reflection.MonoProperty object representing the property @property
7588  * in class @klass.  On error returns NULL and sets @error.
7589  */
7590 MonoReflectionProperty*
7591 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7592 {
7593         MonoReflectionProperty *res;
7594
7595         mono_error_init (error);
7596
7597         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7598         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7599         if (!res)
7600                 return NULL;
7601         res->klass = klass;
7602         res->property = property;
7603         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7604 }
7605
7606 /*
7607  * mono_event_get_object:
7608  * @domain: an app domain
7609  * @klass: a type
7610  * @event: a event
7611  *
7612  * Return an System.Reflection.MonoEvent object representing the event @event
7613  * in class @klass.
7614  */
7615 MonoReflectionEvent*
7616 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7617 {
7618         MonoError error;
7619         MonoReflectionEvent *result;
7620         result = mono_event_get_object_checked (domain, klass, event, &error);
7621         mono_error_cleanup (&error);
7622         return result;
7623 }
7624
7625 /**
7626  * mono_event_get_object_checked:
7627  * @domain: an app domain
7628  * @klass: a type
7629  * @event: a event
7630  * @error: set on error
7631  *
7632  * Return an System.Reflection.MonoEvent object representing the event @event
7633  * in class @klass. On failure sets @error and returns NULL
7634  */
7635 MonoReflectionEvent*
7636 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7637 {
7638         MonoReflectionEvent *res;
7639         MonoReflectionMonoEvent *mono_event;
7640
7641         mono_error_init (error);
7642         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7643         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7644         if (!mono_event)
7645                 return NULL;
7646         mono_event->klass = klass;
7647         mono_event->event = event;
7648         res = (MonoReflectionEvent*)mono_event;
7649         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7650 }
7651
7652 /**
7653  * mono_get_reflection_missing_object:
7654  * @domain: Domain where the object lives
7655  *
7656  * Returns the System.Reflection.Missing.Value singleton object
7657  * (of type System.Reflection.Missing).
7658  *
7659  * Used as the value for ParameterInfo.DefaultValue when Optional
7660  * is present
7661  */
7662 static MonoObject *
7663 mono_get_reflection_missing_object (MonoDomain *domain)
7664 {
7665         MonoError error;
7666         MonoObject *obj;
7667         static MonoClassField *missing_value_field = NULL;
7668         
7669         if (!missing_value_field) {
7670                 MonoClass *missing_klass;
7671                 missing_klass = mono_class_get_missing_class ();
7672                 mono_class_init (missing_klass);
7673                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7674                 g_assert (missing_value_field);
7675         }
7676         obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7677         mono_error_assert_ok (&error);
7678         return obj;
7679 }
7680
7681 static MonoObject*
7682 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7683 {
7684         if (!*dbnull)
7685                 *dbnull = mono_get_dbnull_object (domain);
7686         return *dbnull;
7687 }
7688
7689 static MonoObject*
7690 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7691 {
7692         if (!*reflection_missing)
7693                 *reflection_missing = mono_get_reflection_missing_object (domain);
7694         return *reflection_missing;
7695 }
7696
7697 /*
7698  * mono_param_get_objects:
7699  * @domain: an app domain
7700  * @method: a method
7701  *
7702  * Return an System.Reflection.ParameterInfo array object representing the parameters
7703  * in the method @method.
7704  */
7705 MonoArray*
7706 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7707 {
7708         static MonoClass *System_Reflection_ParameterInfo;
7709         static MonoClass *System_Reflection_ParameterInfo_array;
7710         MonoArray *res = NULL;
7711         MonoReflectionMethod *member = NULL;
7712         MonoReflectionParameter *param = NULL;
7713         char **names = NULL, **blobs = NULL;
7714         guint32 *types = NULL;
7715         MonoType *type = NULL;
7716         MonoObject *dbnull = NULL;
7717         MonoObject *missing = NULL;
7718         MonoMarshalSpec **mspecs = NULL;
7719         MonoMethodSignature *sig = NULL;
7720         MonoVTable *pinfo_vtable;
7721         MonoReflectionType *rt;
7722         int i;
7723
7724         mono_error_init (error);
7725         
7726         if (!System_Reflection_ParameterInfo_array) {
7727                 MonoClass *klass;
7728
7729                 klass = mono_class_get_mono_parameter_info_class ();
7730
7731                 mono_memory_barrier ();
7732                 System_Reflection_ParameterInfo = klass; 
7733
7734         
7735                 klass = mono_array_class_get (klass, 1);
7736                 mono_memory_barrier ();
7737                 System_Reflection_ParameterInfo_array = klass;
7738         }
7739
7740         sig = mono_method_signature_checked (method, error);
7741         if (!mono_error_ok (error))
7742                 goto leave;
7743
7744         if (!sig->param_count) {
7745                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7746                 if (!res)
7747                         goto leave;
7748
7749                 return res;
7750         }
7751
7752         /* Note: the cache is based on the address of the signature into the method
7753          * since we already cache MethodInfos with the method as keys.
7754          */
7755         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7756
7757         member = mono_method_get_object_checked (domain, method, refclass, error);
7758         if (!member)
7759                 goto leave;
7760         names = g_new (char *, sig->param_count);
7761         mono_method_get_param_names (method, (const char **) names);
7762
7763         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7764         mono_method_get_marshal_info (method, mspecs);
7765
7766         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7767         if (!res)
7768                 goto leave;
7769
7770         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7771         for (i = 0; i < sig->param_count; ++i) {
7772                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7773                 if (!param)
7774                         goto leave;
7775
7776                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7777                 if (!rt)
7778                         goto leave;
7779
7780                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7781
7782                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7783
7784                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7785
7786                 param->PositionImpl = i;
7787                 param->AttrsImpl = sig->params [i]->attrs;
7788
7789                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7790                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7791                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7792                         else
7793                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7794                 } else {
7795
7796                         if (!blobs) {
7797                                 blobs = g_new0 (char *, sig->param_count);
7798                                 types = g_new0 (guint32, sig->param_count);
7799                                 get_default_param_value_blobs (method, blobs, types); 
7800                         }
7801
7802                         /* Build MonoType for the type from the Constant Table */
7803                         if (!type)
7804                                 type = g_new0 (MonoType, 1);
7805                         type->type = (MonoTypeEnum)types [i];
7806                         type->data.klass = NULL;
7807                         if (types [i] == MONO_TYPE_CLASS)
7808                                 type->data.klass = mono_defaults.object_class;
7809                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7810                                 /* For enums, types [i] contains the base type */
7811
7812                                         type->type = MONO_TYPE_VALUETYPE;
7813                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7814                         } else
7815                                 type->data.klass = mono_class_from_mono_type (type);
7816
7817                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7818                         if (!is_ok (error))
7819                                 goto leave;
7820                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7821
7822                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7823                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7824                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7825                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7826                                 else
7827                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7828                         }
7829                         
7830                 }
7831
7832                 if (mspecs [i + 1]) {
7833                         MonoReflectionMarshalAsAttribute* mobj;
7834                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7835                         if (!mobj)
7836                                 goto leave;
7837                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7838                 }
7839                 
7840                 mono_array_setref (res, i, param);
7841         }
7842
7843 leave:
7844         g_free (names);
7845         g_free (blobs);
7846         g_free (types);
7847         g_free (type);
7848
7849         if (sig) {
7850                 for (i = sig->param_count; i >= 0; i--) {
7851                         if (mspecs [i])
7852                                 mono_metadata_free_marshal_spec (mspecs [i]);
7853                 }
7854         }
7855         g_free (mspecs);
7856
7857         if (!is_ok (error))
7858                 return NULL;
7859         
7860         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7861 }
7862
7863 MonoArray*
7864 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7865 {
7866         MonoError error;
7867         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7868         mono_error_assert_ok (&error);
7869         return result;
7870 }
7871
7872 /*
7873  * mono_method_body_get_object:
7874  * @domain: an app domain
7875  * @method: a method
7876  *
7877  * Return an System.Reflection.MethodBody object representing the method @method.
7878  */
7879 MonoReflectionMethodBody*
7880 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7881 {
7882         MonoError error;
7883         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7884         mono_error_cleanup (&error);
7885         return result;
7886 }
7887
7888 /**
7889  * mono_method_body_get_object_checked:
7890  * @domain: an app domain
7891  * @method: a method
7892  * @error: set on error
7893  *
7894  * Return an System.Reflection.MethodBody object representing the
7895  * method @method.  On failure, returns NULL and sets @error.
7896  */
7897 MonoReflectionMethodBody*
7898 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7899 {
7900         MonoReflectionMethodBody *ret;
7901         MonoMethodHeader *header;
7902         MonoImage *image;
7903         MonoReflectionType *rt;
7904         guint32 method_rva, local_var_sig_token;
7905         char *ptr;
7906         unsigned char format, flags;
7907         int i;
7908
7909         mono_error_init (error);
7910
7911         /* for compatibility with .net */
7912         if (method_is_dynamic (method)) {
7913                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7914                 return NULL;
7915         }
7916
7917         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7918
7919         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7920                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7921             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7922                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7923             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7924                 return NULL;
7925
7926         image = method->klass->image;
7927         header = mono_method_get_header_checked (method, error);
7928         return_val_if_nok (error, NULL);
7929
7930         if (!image_is_dynamic (image)) {
7931                 /* Obtain local vars signature token */
7932                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7933                 ptr = mono_image_rva_map (image, method_rva);
7934                 flags = *(const unsigned char *) ptr;
7935                 format = flags & METHOD_HEADER_FORMAT_MASK;
7936                 switch (format){
7937                 case METHOD_HEADER_TINY_FORMAT:
7938                         local_var_sig_token = 0;
7939                         break;
7940                 case METHOD_HEADER_FAT_FORMAT:
7941                         ptr += 2;
7942                         ptr += 2;
7943                         ptr += 4;
7944                         local_var_sig_token = read32 (ptr);
7945                         break;
7946                 default:
7947                         g_assert_not_reached ();
7948                 }
7949         } else
7950                 local_var_sig_token = 0; //FIXME
7951
7952         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7953         if (!is_ok (error))
7954                 goto fail;
7955
7956         ret->init_locals = header->init_locals;
7957         ret->max_stack = header->max_stack;
7958         ret->local_var_sig_token = local_var_sig_token;
7959         MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
7960         if (!is_ok (error))
7961                 goto fail;
7962         MONO_OBJECT_SETREF (ret, il, il_arr);
7963         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7964
7965         /* Locals */
7966         MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
7967         if (!is_ok (error))
7968                 goto fail;
7969         MONO_OBJECT_SETREF (ret, locals, locals_arr);
7970         for (i = 0; i < header->num_locals; ++i) {
7971                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7972                 if (!is_ok (error))
7973                         goto fail;
7974
7975                 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7976                 if (!is_ok (error))
7977                         goto fail;
7978
7979                 MONO_OBJECT_SETREF (info, local_type, rt);
7980
7981                 info->is_pinned = header->locals [i]->pinned;
7982                 info->local_index = i;
7983                 mono_array_setref (ret->locals, i, info);
7984         }
7985
7986         /* Exceptions */
7987         MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
7988         if (!is_ok (error))
7989                 goto fail;
7990         MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
7991         for (i = 0; i < header->num_clauses; ++i) {
7992                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7993                 if (!is_ok (error))
7994                         goto fail;
7995                 MonoExceptionClause *clause = &header->clauses [i];
7996
7997                 info->flags = clause->flags;
7998                 info->try_offset = clause->try_offset;
7999                 info->try_length = clause->try_len;
8000                 info->handler_offset = clause->handler_offset;
8001                 info->handler_length = clause->handler_len;
8002                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
8003                         info->filter_offset = clause->data.filter_offset;
8004                 else if (clause->data.catch_class) {
8005                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
8006                         if (!is_ok (error))
8007                                 goto fail;
8008
8009                         MONO_OBJECT_SETREF (info, catch_type, rt);
8010                 }
8011
8012                 mono_array_setref (ret->clauses, i, info);
8013         }
8014
8015         mono_metadata_free_mh (header);
8016         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
8017         return ret;
8018
8019 fail:
8020         mono_metadata_free_mh (header);
8021         return NULL;
8022 }
8023
8024 /**
8025  * mono_get_dbnull_object:
8026  * @domain: Domain where the object lives
8027  *
8028  * Returns the System.DBNull.Value singleton object
8029  *
8030  * Used as the value for ParameterInfo.DefaultValue 
8031  */
8032 MonoObject *
8033 mono_get_dbnull_object (MonoDomain *domain)
8034 {
8035         MonoError error;
8036         MonoObject *obj;
8037         static MonoClassField *dbnull_value_field = NULL;
8038         
8039         if (!dbnull_value_field) {
8040                 MonoClass *dbnull_klass;
8041                 dbnull_klass = mono_class_get_dbnull_class ();
8042                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
8043                 g_assert (dbnull_value_field);
8044         }
8045         obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
8046         mono_error_assert_ok (&error);
8047         return obj;
8048 }
8049
8050 static void
8051 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
8052 {
8053         guint32 param_index, i, lastp, crow = 0;
8054         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
8055         gint32 idx;
8056
8057         MonoClass *klass = method->klass;
8058         MonoImage *image = klass->image;
8059         MonoMethodSignature *methodsig = mono_method_signature (method);
8060
8061         MonoTableInfo *constt;
8062         MonoTableInfo *methodt;
8063         MonoTableInfo *paramt;
8064
8065         if (!methodsig->param_count)
8066                 return;
8067
8068         mono_class_init (klass);
8069
8070         if (image_is_dynamic (klass->image)) {
8071                 MonoReflectionMethodAux *aux;
8072                 if (method->is_inflated)
8073                         method = ((MonoMethodInflated*)method)->declaring;
8074                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8075                 if (aux && aux->param_defaults) {
8076                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
8077                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
8078                 }
8079                 return;
8080         }
8081
8082         methodt = &klass->image->tables [MONO_TABLE_METHOD];
8083         paramt = &klass->image->tables [MONO_TABLE_PARAM];
8084         constt = &image->tables [MONO_TABLE_CONSTANT];
8085
8086         idx = mono_method_get_index (method) - 1;
8087         g_assert (idx != -1);
8088
8089         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
8090         if (idx + 1 < methodt->rows)
8091                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
8092         else
8093                 lastp = paramt->rows + 1;
8094
8095         for (i = param_index; i < lastp; ++i) {
8096                 guint32 paramseq;
8097
8098                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
8099                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
8100
8101                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
8102                         continue;
8103
8104                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
8105                 if (!crow) {
8106                         continue;
8107                 }
8108         
8109                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
8110                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
8111                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8112         }
8113
8114         return;
8115 }
8116
8117 MonoObject *
8118 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8119 {
8120         void *retval;
8121         MonoClass *klass;
8122         MonoObject *object;
8123         MonoType *basetype = type;
8124
8125         mono_error_init (error);
8126
8127         if (!blob)
8128                 return NULL;
8129         
8130         klass = mono_class_from_mono_type (type);
8131         if (klass->valuetype) {
8132                 object = mono_object_new_checked (domain, klass, error);
8133                 return_val_if_nok (error, NULL);
8134                 retval = ((gchar *) object + sizeof (MonoObject));
8135                 if (klass->enumtype)
8136                         basetype = mono_class_enum_basetype (klass);
8137         } else {
8138                 retval = &object;
8139         }
8140                         
8141         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval, error))
8142                 return object;
8143         else
8144                 return NULL;
8145 }
8146
8147 static int
8148 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8149         int found_sep;
8150         char *s;
8151         gboolean quoted = FALSE;
8152
8153         memset (assembly, 0, sizeof (MonoAssemblyName));
8154         assembly->culture = "";
8155         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8156
8157         if (*p == '"') {
8158                 quoted = TRUE;
8159                 p++;
8160         }
8161         assembly->name = p;
8162         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8163                 p++;
8164         if (quoted) {
8165                 if (*p != '"')
8166                         return 1;
8167                 *p = 0;
8168                 p++;
8169         }
8170         if (*p != ',')
8171                 return 1;
8172         *p = 0;
8173         /* Remove trailing whitespace */
8174         s = p - 1;
8175         while (*s && g_ascii_isspace (*s))
8176                 *s-- = 0;
8177         p ++;
8178         while (g_ascii_isspace (*p))
8179                 p++;
8180         while (*p) {
8181                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8182                         p += 8;
8183                         assembly->major = strtoul (p, &s, 10);
8184                         if (s == p || *s != '.')
8185                                 return 1;
8186                         p = ++s;
8187                         assembly->minor = strtoul (p, &s, 10);
8188                         if (s == p || *s != '.')
8189                                 return 1;
8190                         p = ++s;
8191                         assembly->build = strtoul (p, &s, 10);
8192                         if (s == p || *s != '.')
8193                                 return 1;
8194                         p = ++s;
8195                         assembly->revision = strtoul (p, &s, 10);
8196                         if (s == p)
8197                                 return 1;
8198                         p = s;
8199                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8200                         p += 8;
8201                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8202                                 assembly->culture = "";
8203                                 p += 7;
8204                         } else {
8205                                 assembly->culture = p;
8206                                 while (*p && *p != ',') {
8207                                         p++;
8208                                 }
8209                         }
8210                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8211                         p += 15;
8212                         if (strncmp (p, "null", 4) == 0) {
8213                                 p += 4;
8214                         } else {
8215                                 int len;
8216                                 gchar *start = p;
8217                                 while (*p && *p != ',') {
8218                                         p++;
8219                                 }
8220                                 len = (p - start + 1);
8221                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8222                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8223                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8224                         }
8225                 } else {
8226                         while (*p && *p != ',')
8227                                 p++;
8228                 }
8229                 found_sep = 0;
8230                 while (g_ascii_isspace (*p) || *p == ',') {
8231                         *p++ = 0;
8232                         found_sep = 1;
8233                         continue;
8234                 }
8235                 /* failed */
8236                 if (!found_sep)
8237                         return 1;
8238         }
8239
8240         return 0;
8241 }
8242
8243 /*
8244  * mono_reflection_parse_type:
8245  * @name: type name
8246  *
8247  * Parse a type name as accepted by the GetType () method and output the info
8248  * extracted in the info structure.
8249  * the name param will be mangled, so, make a copy before passing it to this function.
8250  * The fields in info will be valid until the memory pointed to by name is valid.
8251  *
8252  * See also mono_type_get_name () below.
8253  *
8254  * Returns: 0 on parse error.
8255  */
8256 static int
8257 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8258                              MonoTypeNameParse *info)
8259 {
8260         char *start, *p, *w, *last_point, *startn;
8261         int in_modifiers = 0;
8262         int isbyref = 0, rank = 0, isptr = 0;
8263
8264         start = p = w = name;
8265
8266         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8267         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8268         info->name = info->name_space = NULL;
8269         info->nested = NULL;
8270         info->modifiers = NULL;
8271         info->type_arguments = NULL;
8272
8273         /* last_point separates the namespace from the name */
8274         last_point = NULL;
8275         /* Skips spaces */
8276         while (*p == ' ') p++, start++, w++, name++;
8277
8278         while (*p) {
8279                 switch (*p) {
8280                 case '+':
8281                         *p = 0; /* NULL terminate the name */
8282                         startn = p + 1;
8283                         info->nested = g_list_append (info->nested, startn);
8284                         /* we have parsed the nesting namespace + name */
8285                         if (info->name)
8286                                 break;
8287                         if (last_point) {
8288                                 info->name_space = start;
8289                                 *last_point = 0;
8290                                 info->name = last_point + 1;
8291                         } else {
8292                                 info->name_space = (char *)"";
8293                                 info->name = start;
8294                         }
8295                         break;
8296                 case '.':
8297                         last_point = p;
8298                         break;
8299                 case '\\':
8300                         ++p;
8301                         break;
8302                 case '&':
8303                 case '*':
8304                 case '[':
8305                 case ',':
8306                 case ']':
8307                         in_modifiers = 1;
8308                         break;
8309                 default:
8310                         break;
8311                 }
8312                 if (in_modifiers)
8313                         break;
8314                 // *w++ = *p++;
8315                 p++;
8316         }
8317         
8318         if (!info->name) {
8319                 if (last_point) {
8320                         info->name_space = start;
8321                         *last_point = 0;
8322                         info->name = last_point + 1;
8323                 } else {
8324                         info->name_space = (char *)"";
8325                         info->name = start;
8326                 }
8327         }
8328         while (*p) {
8329                 switch (*p) {
8330                 case '&':
8331                         if (isbyref) /* only one level allowed by the spec */
8332                                 return 0;
8333                         isbyref = 1;
8334                         isptr = 0;
8335                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8336                         *p++ = 0;
8337                         break;
8338                 case '*':
8339                         if (isbyref) /* pointer to ref not okay */
8340                                 return 0;
8341                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8342                         isptr = 1;
8343                         *p++ = 0;
8344                         break;
8345                 case '[':
8346                         if (isbyref) /* array of ref and generic ref are not okay */
8347                                 return 0;
8348                         //Decide if it's an array of a generic argument list
8349                         *p++ = 0;
8350
8351                         if (!*p) //XXX test
8352                                 return 0;
8353                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8354                                 isptr = 0;
8355                                 rank = 1;
8356                                 while (*p) {
8357                                         if (*p == ']')
8358                                                 break;
8359                                         if (*p == ',')
8360                                                 rank++;
8361                                         else if (*p == '*') /* '*' means unknown lower bound */
8362                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8363                                         else
8364                                                 return 0;
8365                                         ++p;
8366                                 }
8367                                 if (*p++ != ']')
8368                                         return 0;
8369                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8370                         } else {
8371                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8372                                         return 0;
8373                                 isptr = 0;
8374                                 info->type_arguments = g_ptr_array_new ();
8375                                 while (*p) {
8376                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8377                                         gboolean fqname = FALSE;
8378
8379                                         g_ptr_array_add (info->type_arguments, subinfo);
8380
8381                                         while (*p == ' ') p++;
8382                                         if (*p == '[') {
8383                                                 p++;
8384                                                 fqname = TRUE;
8385                                         }
8386
8387                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8388                                                 return 0;
8389
8390                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8391                                         if (fqname && (*p != ']')) {
8392                                                 char *aname;
8393
8394                                                 if (*p != ',')
8395                                                         return 0;
8396                                                 *p++ = 0;
8397
8398                                                 aname = p;
8399                                                 while (*p && (*p != ']'))
8400                                                         p++;
8401
8402                                                 if (*p != ']')
8403                                                         return 0;
8404
8405                                                 *p++ = 0;
8406                                                 while (*aname) {
8407                                                         if (g_ascii_isspace (*aname)) {
8408                                                                 ++aname;
8409                                                                 continue;
8410                                                         }
8411                                                         break;
8412                                                 }
8413                                                 if (!*aname ||
8414                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8415                                                         return 0;
8416                                         } else if (fqname && (*p == ']')) {
8417                                                 *p++ = 0;
8418                                         }
8419                                         if (*p == ']') {
8420                                                 *p++ = 0;
8421                                                 break;
8422                                         } else if (!*p) {
8423                                                 return 0;
8424                                         }
8425                                         *p++ = 0;
8426                                 }
8427                         }
8428                         break;
8429                 case ']':
8430                         if (is_recursed)
8431                                 goto end;
8432                         return 0;
8433                 case ',':
8434                         if (is_recursed)
8435                                 goto end;
8436                         *p++ = 0;
8437                         while (*p) {
8438                                 if (g_ascii_isspace (*p)) {
8439                                         ++p;
8440                                         continue;
8441                                 }
8442                                 break;
8443                         }
8444                         if (!*p)
8445                                 return 0; /* missing assembly name */
8446                         if (!assembly_name_to_aname (&info->assembly, p))
8447                                 return 0;
8448                         break;
8449                 default:
8450                         return 0;
8451                 }
8452                 if (info->assembly.name)
8453                         break;
8454         }
8455         // *w = 0; /* terminate class name */
8456  end:
8457         if (!info->name || !*info->name)
8458                 return 0;
8459         if (endptr)
8460                 *endptr = p;
8461         /* add other consistency checks */
8462         return 1;
8463 }
8464
8465
8466 /**
8467  * mono_identifier_unescape_type_name_chars:
8468  * @identifier: the display name of a mono type
8469  *
8470  * Returns:
8471  *  The name in internal form, that is without escaping backslashes.
8472  *
8473  *  The string is modified in place!
8474  */
8475 char*
8476 mono_identifier_unescape_type_name_chars(char* identifier)
8477 {
8478         char *w, *r;
8479         if (!identifier)
8480                 return NULL;
8481         for (w = r = identifier; *r != 0; r++)
8482         {
8483                 char c = *r;
8484                 if (c == '\\') {
8485                         r++;
8486                         if (*r == 0)
8487                                 break;
8488                         c = *r;
8489                 }
8490                 *w = c;
8491                 w++;
8492         }
8493         if (w != r)
8494                 *w = 0;
8495         return identifier;
8496 }
8497
8498 void
8499 mono_identifier_unescape_info (MonoTypeNameParse* info);
8500
8501 static void
8502 unescape_each_type_argument(void* data, void* user_data)
8503 {
8504         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8505         mono_identifier_unescape_info (info);
8506 }
8507
8508 static void
8509 unescape_each_nested_name (void* data, void* user_data)
8510 {
8511         char* nested_name = (char*) data;
8512         mono_identifier_unescape_type_name_chars(nested_name);
8513 }
8514
8515 /**
8516  * mono_identifier_unescape_info:
8517  *
8518  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8519  *
8520  * Returns: nothing.
8521  *
8522  * Destructively updates the info by unescaping the identifiers that
8523  * comprise the type namespace, name, nested types (if any) and
8524  * generic type arguments (if any).
8525  *
8526  * The resulting info has the names in internal form.
8527  *
8528  */
8529 void
8530 mono_identifier_unescape_info (MonoTypeNameParse *info)
8531 {
8532         if (!info)
8533                 return;
8534         mono_identifier_unescape_type_name_chars(info->name_space);
8535         mono_identifier_unescape_type_name_chars(info->name);
8536         // but don't escape info->assembly
8537         if (info->type_arguments)
8538                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8539         if (info->nested)
8540                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8541 }
8542
8543 int
8544 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8545 {
8546         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8547         if (ok) {
8548                 mono_identifier_unescape_info (info);
8549         }
8550         return ok;
8551 }
8552
8553 static MonoType*
8554 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8555 {
8556         gboolean type_resolve = FALSE;
8557         MonoType *type;
8558         MonoImage *rootimage = image;
8559
8560         mono_error_init (error);
8561
8562         if (info->assembly.name) {
8563                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8564                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8565                         /* 
8566                          * This could happen in the AOT compiler case when the search hook is not
8567                          * installed.
8568                          */
8569                         assembly = image->assembly;
8570                 if (!assembly) {
8571                         /* then we must load the assembly ourselve - see #60439 */
8572                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8573                         if (!assembly)
8574                                 return NULL;
8575                 }
8576                 image = assembly->image;
8577         } else if (!image) {
8578                 image = mono_defaults.corlib;
8579         }
8580
8581         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8582         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8583                 /* ignore the error and try again */
8584                 mono_error_cleanup (error);
8585                 mono_error_init (error);
8586                 image = mono_defaults.corlib;
8587                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8588         }
8589
8590         return type;
8591 }
8592
8593 /**
8594  * mono_reflection_get_type_internal:
8595  *
8596  * Returns: may return NULL on success, sets error on failure.
8597  */
8598 static MonoType*
8599 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8600 {
8601         MonoClass *klass;
8602         GList *mod;
8603         int modval;
8604         gboolean bounded = FALSE;
8605         
8606         mono_error_init (error);
8607         if (!image)
8608                 image = mono_defaults.corlib;
8609
8610         if (!rootimage)
8611                 rootimage = mono_defaults.corlib;
8612
8613         if (ignorecase)
8614                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8615         else
8616                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8617
8618         if (!klass)
8619                 return NULL;
8620
8621         for (mod = info->nested; mod; mod = mod->next) {
8622                 gpointer iter = NULL;
8623                 MonoClass *parent;
8624
8625                 parent = klass;
8626                 mono_class_init (parent);
8627
8628                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8629                         char *lastp;
8630                         char *nested_name, *nested_nspace;
8631                         gboolean match = TRUE;
8632
8633                         lastp = strrchr ((const char *)mod->data, '.');
8634                         if (lastp) {
8635                                 /* Nested classes can have namespaces */
8636                                 int nspace_len;
8637
8638                                 nested_name = g_strdup (lastp + 1);
8639                                 nspace_len = lastp - (char*)mod->data;
8640                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8641                                 memcpy (nested_nspace, mod->data, nspace_len);
8642                                 nested_nspace [nspace_len] = '\0';
8643
8644                         } else {
8645                                 nested_name = (char *)mod->data;
8646                                 nested_nspace = NULL;
8647                         }
8648
8649                         if (nested_nspace) {
8650                                 if (ignorecase) {
8651                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8652                                                 match = FALSE;
8653                                 } else {
8654                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8655                                                 match = FALSE;
8656                                 }
8657                         }
8658                         if (match) {
8659                                 if (ignorecase) {
8660                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8661                                                 match = FALSE;
8662                                 } else {
8663                                         if (strcmp (klass->name, nested_name) != 0)
8664                                                 match = FALSE;
8665                                 }
8666                         }
8667                         if (lastp) {
8668                                 g_free (nested_name);
8669                                 g_free (nested_nspace);
8670                         }
8671                         if (match)
8672                                 break;
8673                 }
8674
8675                 if (!klass)
8676                         break;
8677         }
8678         if (!klass)
8679                 return NULL;
8680
8681         if (info->type_arguments) {
8682                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8683                 MonoReflectionType *the_type;
8684                 MonoType *instance;
8685                 int i;
8686
8687                 for (i = 0; i < info->type_arguments->len; i++) {
8688                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8689
8690                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8691                         if (!type_args [i]) {
8692                                 g_free (type_args);
8693                                 return NULL;
8694                         }
8695                 }
8696
8697                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8698                 if (!the_type)
8699                         return NULL;
8700
8701                 instance = mono_reflection_bind_generic_parameters (
8702                         the_type, info->type_arguments->len, type_args, error);
8703
8704                 g_free (type_args);
8705                 if (!instance)
8706                         return NULL;
8707
8708                 klass = mono_class_from_mono_type (instance);
8709         }
8710
8711         for (mod = info->modifiers; mod; mod = mod->next) {
8712                 modval = GPOINTER_TO_UINT (mod->data);
8713                 if (!modval) { /* byref: must be last modifier */
8714                         return &klass->this_arg;
8715                 } else if (modval == -1) {
8716                         klass = mono_ptr_class_get (&klass->byval_arg);
8717                 } else if (modval == -2) {
8718                         bounded = TRUE;
8719                 } else { /* array rank */
8720                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8721                 }
8722         }
8723
8724         return &klass->byval_arg;
8725 }
8726
8727 /*
8728  * mono_reflection_get_type:
8729  * @image: a metadata context
8730  * @info: type description structure
8731  * @ignorecase: flag for case-insensitive string compares
8732  * @type_resolve: whenever type resolve was already tried
8733  *
8734  * Build a MonoType from the type description in @info.
8735  * 
8736  */
8737
8738 MonoType*
8739 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8740         MonoError error;
8741         MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8742         mono_error_cleanup (&error);
8743         return result;
8744 }
8745
8746 /**
8747  * mono_reflection_get_type_checked:
8748  * @rootimage: the image of the currently active managed caller
8749  * @image: a metadata context
8750  * @info: type description structure
8751  * @ignorecase: flag for case-insensitive string compares
8752  * @type_resolve: whenever type resolve was already tried
8753  * @error: set on error.
8754  *
8755  * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8756  *
8757  */
8758 MonoType*
8759 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8760         mono_error_init (error);
8761         return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
8762 }
8763
8764
8765 static MonoType*
8766 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8767 {
8768         MonoReflectionAssemblyBuilder *abuilder;
8769         MonoType *type;
8770         int i;
8771
8772         mono_error_init (error);
8773         g_assert (assembly_is_dynamic (assembly));
8774         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8775         if (!abuilder)
8776                 return NULL;
8777
8778         /* Enumerate all modules */
8779
8780         type = NULL;
8781         if (abuilder->modules) {
8782                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8783                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8784                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8785                         if (type)
8786                                 break;
8787                         if (!mono_error_ok (error))
8788                                 return NULL;
8789                 }
8790         }
8791
8792         if (!type && abuilder->loaded_modules) {
8793                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8794                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8795                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8796                         if (type)
8797                                 break;
8798                         if (!mono_error_ok (error))
8799                                 return NULL;
8800                 }
8801         }
8802
8803         return type;
8804 }
8805         
8806 MonoType*
8807 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8808 {
8809         MonoType *type;
8810         MonoReflectionAssembly *assembly;
8811         GString *fullName;
8812         GList *mod;
8813
8814         mono_error_init (error);
8815
8816         if (image && image_is_dynamic (image))
8817                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8818         else {
8819                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8820         }
8821         return_val_if_nok (error, NULL);
8822
8823         if (type)
8824                 return type;
8825         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8826                 return NULL;
8827
8828         if (type_resolve) {
8829                 if (*type_resolve) 
8830                         return NULL;
8831                 else
8832                         *type_resolve = TRUE;
8833         }
8834         
8835         /* Reconstruct the type name */
8836         fullName = g_string_new ("");
8837         if (info->name_space && (info->name_space [0] != '\0'))
8838                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8839         else
8840                 g_string_printf (fullName, "%s", info->name);
8841         for (mod = info->nested; mod; mod = mod->next)
8842                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8843
8844         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8845         if (!is_ok (error)) {
8846                 g_string_free (fullName, TRUE);
8847                 return NULL;
8848         }
8849
8850         if (assembly) {
8851                 if (assembly_is_dynamic (assembly->assembly))
8852                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8853                                                                           info, ignorecase, error);
8854                 else
8855                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8856                                                                   info, ignorecase, error);
8857         }
8858         g_string_free (fullName, TRUE);
8859         return_val_if_nok (error, NULL);
8860         return type;
8861 }
8862
8863 void
8864 mono_reflection_free_type_info (MonoTypeNameParse *info)
8865 {
8866         g_list_free (info->modifiers);
8867         g_list_free (info->nested);
8868
8869         if (info->type_arguments) {
8870                 int i;
8871
8872                 for (i = 0; i < info->type_arguments->len; i++) {
8873                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8874
8875                         mono_reflection_free_type_info (subinfo);
8876                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8877                         g_free (subinfo);
8878                 }
8879
8880                 g_ptr_array_free (info->type_arguments, TRUE);
8881         }
8882 }
8883
8884 /*
8885  * mono_reflection_type_from_name:
8886  * @name: type name.
8887  * @image: a metadata context (can be NULL).
8888  *
8889  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8890  * it defaults to get the type from @image or, if @image is NULL or loading
8891  * from it fails, uses corlib.
8892  * 
8893  */
8894 MonoType*
8895 mono_reflection_type_from_name (char *name, MonoImage *image)
8896 {
8897         MonoError error;
8898         MonoType  *result = mono_reflection_type_from_name_checked (name, image, &error);
8899         mono_error_cleanup (&error);
8900         return result;
8901 }
8902
8903 /**
8904  * mono_reflection_type_from_name_checked:
8905  * @name: type name.
8906  * @image: a metadata context (can be NULL).
8907  * @error: set on errror.
8908  *
8909  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8910  * it defaults to get the type from @image or, if @image is NULL or loading
8911  * from it fails, uses corlib.  On failure returns NULL and sets @error.
8912  * 
8913  */
8914 MonoType*
8915 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8916 {
8917         MonoType *type = NULL;
8918         MonoTypeNameParse info;
8919         char *tmp;
8920
8921         mono_error_init (error);
8922         /* Make a copy since parse_type modifies its argument */
8923         tmp = g_strdup (name);
8924         
8925         /*g_print ("requested type %s\n", str);*/
8926         if (mono_reflection_parse_type (tmp, &info)) {
8927                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8928                 if (!is_ok (error)) {
8929                         g_free (tmp);
8930                         mono_reflection_free_type_info (&info);
8931                         return NULL;
8932                 }
8933         }
8934
8935         g_free (tmp);
8936         mono_reflection_free_type_info (&info);
8937         return type;
8938 }
8939
8940 /*
8941  * mono_reflection_get_token:
8942  *
8943  *   Return the metadata token of OBJ which should be an object
8944  * representing a metadata element.
8945  */
8946 guint32
8947 mono_reflection_get_token (MonoObject *obj)
8948 {
8949         MonoError error;
8950         guint32 result = mono_reflection_get_token_checked (obj, &error);
8951         mono_error_assert_ok (&error);
8952         return result;
8953 }
8954
8955 /**
8956  * mono_reflection_get_token_checked:
8957  * @obj: the object
8958  * @error: set on error
8959  *
8960  *   Return the metadata token of @obj which should be an object
8961  * representing a metadata element.  On failure sets @error.
8962  */
8963 guint32
8964 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8965 {
8966         MonoClass *klass;
8967         guint32 token = 0;
8968
8969         mono_error_init (error);
8970
8971         klass = obj->vtable->klass;
8972
8973         if (strcmp (klass->name, "MethodBuilder") == 0) {
8974                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8975
8976                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8977         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8978                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8979
8980                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8981         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8982                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8983
8984                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8985         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8986                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8987                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8988         } else if (strcmp (klass->name, "RuntimeType") == 0) {
8989                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8990                 return_val_if_nok (error, 0);
8991                 MonoClass *mc = mono_class_from_mono_type (type);
8992                 if (!mono_class_init (mc)) {
8993                         mono_error_set_for_class_failure (error, mc);
8994                         return 0;
8995                 }
8996
8997                 token = mc->type_token;
8998         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8999                    strcmp (klass->name, "MonoMethod") == 0 ||
9000                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
9001                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
9002                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
9003                 if (m->method->is_inflated) {
9004                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
9005                         return inflated->declaring->token;
9006                 } else {
9007                         token = m->method->token;
9008                 }
9009         } else if (strcmp (klass->name, "MonoField") == 0) {
9010                 MonoReflectionField *f = (MonoReflectionField*)obj;
9011
9012                 if (is_field_on_inst (f->field)) {
9013                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
9014
9015                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
9016                                 int field_index = f->field - dgclass->fields;
9017                                 MonoObject *obj;
9018
9019                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
9020                                 obj = dgclass->field_objects [field_index];
9021                                 return mono_reflection_get_token_checked (obj, error);
9022                         }
9023                 }
9024                 token = mono_class_get_field_token (f->field);
9025         } else if (strcmp (klass->name, "MonoProperty") == 0) {
9026                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
9027
9028                 token = mono_class_get_property_token (p->property);
9029         } else if (strcmp (klass->name, "MonoEvent") == 0) {
9030                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
9031
9032                 token = mono_class_get_event_token (p->event);
9033         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
9034                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
9035                 MonoClass *member_class = mono_object_class (p->MemberImpl);
9036                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
9037
9038                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
9039         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
9040                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
9041
9042                 token = m->token;
9043         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
9044                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
9045         } else {
9046                 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
9047                                                 klass->name_space, klass->name);
9048                 return 0;
9049         }
9050
9051         return token;
9052 }
9053
9054 /*
9055  * Load the type with name @n on behalf of image @image.  On failure sets @error and returns NULL.
9056  * The @is_enum flag only affects the error message that's displayed on failure.
9057  */
9058 static MonoType*
9059 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
9060 {
9061         MonoError inner_error;
9062         MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
9063         if (!t) {
9064                 mono_error_set_type_load_name (error, g_strdup(n), NULL,
9065                                                "Could not load %s %s while decoding custom attribute: %s",
9066                                                is_enum ? "enum type": "type",
9067                                                n,
9068                                                mono_error_get_message (&inner_error));
9069                 mono_error_cleanup (&inner_error);
9070                 return NULL;
9071         }
9072         return t;
9073 }
9074
9075 static MonoClass*
9076 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
9077 {
9078         char *n;
9079         MonoType *t;
9080         int slen = mono_metadata_decode_value (p, &p);
9081
9082         mono_error_init (error);
9083
9084         n = (char *)g_memdup (p, slen + 1);
9085         n [slen] = 0;
9086         t = cattr_type_from_name (n, image, TRUE, error);
9087         g_free (n);
9088         return_val_if_nok (error, NULL);
9089         p += slen;
9090         *end = p;
9091         return mono_class_from_mono_type (t);
9092 }
9093
9094 static void*
9095 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
9096 {
9097         int slen, type = t->type;
9098         MonoClass *tklass = t->data.klass;
9099
9100         mono_error_init (error);
9101
9102 handle_enum:
9103         switch (type) {
9104         case MONO_TYPE_U1:
9105         case MONO_TYPE_I1:
9106         case MONO_TYPE_BOOLEAN: {
9107                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
9108                 *bval = *p;
9109                 *end = p + 1;
9110                 return bval;
9111         }
9112         case MONO_TYPE_CHAR:
9113         case MONO_TYPE_U2:
9114         case MONO_TYPE_I2: {
9115                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
9116                 *val = read16 (p);
9117                 *end = p + 2;
9118                 return val;
9119         }
9120 #if SIZEOF_VOID_P == 4
9121         case MONO_TYPE_U:
9122         case MONO_TYPE_I:
9123 #endif
9124         case MONO_TYPE_R4:
9125         case MONO_TYPE_U4:
9126         case MONO_TYPE_I4: {
9127                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9128                 *val = read32 (p);
9129                 *end = p + 4;
9130                 return val;
9131         }
9132 #if SIZEOF_VOID_P == 8
9133         case MONO_TYPE_U: /* error out instead? this should probably not happen */
9134         case MONO_TYPE_I:
9135 #endif
9136         case MONO_TYPE_U8:
9137         case MONO_TYPE_I8: {
9138                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9139                 *val = read64 (p);
9140                 *end = p + 8;
9141                 return val;
9142         }
9143         case MONO_TYPE_R8: {
9144                 double *val = (double *)g_malloc (sizeof (double));
9145                 readr8 (p, val);
9146                 *end = p + 8;
9147                 return val;
9148         }
9149         case MONO_TYPE_VALUETYPE:
9150                 if (t->data.klass->enumtype) {
9151                         type = mono_class_enum_basetype (t->data.klass)->type;
9152                         goto handle_enum;
9153                 } else {
9154                         MonoClass *k =  t->data.klass;
9155                         
9156                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9157                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9158                                 *val = read64 (p);
9159                                 *end = p + 8;
9160                                 return val;
9161                         }
9162                 }
9163                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9164                 break;
9165                 
9166         case MONO_TYPE_STRING:
9167                 if (*p == (char)0xFF) {
9168                         *end = p + 1;
9169                         return NULL;
9170                 }
9171                 slen = mono_metadata_decode_value (p, &p);
9172                 *end = p + slen;
9173                 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
9174         case MONO_TYPE_CLASS: {
9175                 MonoReflectionType *rt;
9176                 char *n;
9177                 MonoType *t;
9178                 if (*p == (char)0xFF) {
9179                         *end = p + 1;
9180                         return NULL;
9181                 }
9182 handle_type:
9183                 slen = mono_metadata_decode_value (p, &p);
9184                 n = (char *)g_memdup (p, slen + 1);
9185                 n [slen] = 0;
9186                 t = cattr_type_from_name (n, image, FALSE, error);
9187                 g_free (n);
9188                 return_val_if_nok (error, NULL);
9189                 *end = p + slen;
9190
9191                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9192                 if (!mono_error_ok (error))
9193                         return NULL;
9194
9195                 return rt;
9196         }
9197         case MONO_TYPE_OBJECT: {
9198                 char subt = *p++;
9199                 MonoObject *obj;
9200                 MonoClass *subc = NULL;
9201                 void *val;
9202
9203                 if (subt == 0x50) {
9204                         goto handle_type;
9205                 } else if (subt == 0x0E) {
9206                         type = MONO_TYPE_STRING;
9207                         goto handle_enum;
9208                 } else if (subt == 0x1D) {
9209                         MonoType simple_type = {{0}};
9210                         int etype = *p;
9211                         p ++;
9212
9213                         type = MONO_TYPE_SZARRAY;
9214                         if (etype == 0x50) {
9215                                 tklass = mono_defaults.systemtype_class;
9216                         } else if (etype == 0x55) {
9217                                 tklass = load_cattr_enum_type (image, p, &p, error);
9218                                 if (!mono_error_ok (error))
9219                                         return NULL;
9220                         } else {
9221                                 if (etype == 0x51)
9222                                         /* See Partition II, Appendix B3 */
9223                                         etype = MONO_TYPE_OBJECT;
9224                                 simple_type.type = (MonoTypeEnum)etype;
9225                                 tklass = mono_class_from_mono_type (&simple_type);
9226                         }
9227                         goto handle_enum;
9228                 } else if (subt == 0x55) {
9229                         char *n;
9230                         MonoType *t;
9231                         slen = mono_metadata_decode_value (p, &p);
9232                         n = (char *)g_memdup (p, slen + 1);
9233                         n [slen] = 0;
9234                         t = cattr_type_from_name (n, image, FALSE, error);
9235                         g_free (n);
9236                         return_val_if_nok (error, NULL);
9237                         p += slen;
9238                         subc = mono_class_from_mono_type (t);
9239                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9240                         MonoType simple_type = {{0}};
9241                         simple_type.type = (MonoTypeEnum)subt;
9242                         subc = mono_class_from_mono_type (&simple_type);
9243                 } else {
9244                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9245                 }
9246                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9247                 obj = NULL;
9248                 if (mono_error_ok (error)) {
9249                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
9250                         g_assert (!subc->has_references);
9251                         if (mono_error_ok (error))
9252                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9253                 }
9254
9255                 g_free (val);
9256                 return obj;
9257         }
9258         case MONO_TYPE_SZARRAY: {
9259                 MonoArray *arr;
9260                 guint32 i, alen, basetype;
9261                 alen = read32 (p);
9262                 p += 4;
9263                 if (alen == 0xffffffff) {
9264                         *end = p;
9265                         return NULL;
9266                 }
9267                 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
9268                 return_val_if_nok (error, NULL);
9269                 basetype = tklass->byval_arg.type;
9270                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9271                         basetype = mono_class_enum_basetype (tklass)->type;
9272                 switch (basetype)
9273                 {
9274                         case MONO_TYPE_U1:
9275                         case MONO_TYPE_I1:
9276                         case MONO_TYPE_BOOLEAN:
9277                                 for (i = 0; i < alen; i++) {
9278                                         MonoBoolean val = *p++;
9279                                         mono_array_set (arr, MonoBoolean, i, val);
9280                                 }
9281                                 break;
9282                         case MONO_TYPE_CHAR:
9283                         case MONO_TYPE_U2:
9284                         case MONO_TYPE_I2:
9285                                 for (i = 0; i < alen; i++) {
9286                                         guint16 val = read16 (p);
9287                                         mono_array_set (arr, guint16, i, val);
9288                                         p += 2;
9289                                 }
9290                                 break;
9291                         case MONO_TYPE_R4:
9292                         case MONO_TYPE_U4:
9293                         case MONO_TYPE_I4:
9294                                 for (i = 0; i < alen; i++) {
9295                                         guint32 val = read32 (p);
9296                                         mono_array_set (arr, guint32, i, val);
9297                                         p += 4;
9298                                 }
9299                                 break;
9300                         case MONO_TYPE_R8:
9301                                 for (i = 0; i < alen; i++) {
9302                                         double val;
9303                                         readr8 (p, &val);
9304                                         mono_array_set (arr, double, i, val);
9305                                         p += 8;
9306                                 }
9307                                 break;
9308                         case MONO_TYPE_U8:
9309                         case MONO_TYPE_I8:
9310                                 for (i = 0; i < alen; i++) {
9311                                         guint64 val = read64 (p);
9312                                         mono_array_set (arr, guint64, i, val);
9313                                         p += 8;
9314                                 }
9315                                 break;
9316                         case MONO_TYPE_CLASS:
9317                         case MONO_TYPE_OBJECT:
9318                         case MONO_TYPE_STRING:
9319                         case MONO_TYPE_SZARRAY:
9320                                 for (i = 0; i < alen; i++) {
9321                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9322                                         if (!mono_error_ok (error))
9323                                                 return NULL;
9324                                         mono_array_setref (arr, i, item);
9325                                 }
9326                                 break;
9327                         default:
9328                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9329                 }
9330                 *end=p;
9331                 return arr;
9332         }
9333         default:
9334                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9335         }
9336         return NULL;
9337 }
9338
9339 static MonoObject*
9340 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9341 {
9342         mono_error_init (error);
9343
9344         gboolean is_ref = type_is_reference (t);
9345
9346         void *val = load_cattr_value (image, t, p, end, error);
9347         if (!is_ok (error)) {
9348                 if (is_ref)
9349                         g_free (val);
9350                 return NULL;
9351         }
9352
9353         if (is_ref)
9354                 return (MonoObject*)val;
9355
9356         MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9357         g_free (val);
9358         return boxed;
9359 }
9360
9361 static MonoObject*
9362 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9363 {
9364         static MonoMethod *ctor;
9365         MonoObject *retval;
9366         void *params [2], *unboxed;
9367
9368         mono_error_init (error);
9369
9370         if (!ctor)
9371                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9372         
9373         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9374         return_val_if_nok (error, NULL);
9375
9376         params [1] = val;
9377         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9378         return_val_if_nok (error, NULL);
9379         unboxed = mono_object_unbox (retval);
9380
9381         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9382         return_val_if_nok (error, NULL);
9383
9384         return retval;
9385 }
9386
9387 static MonoObject*
9388 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9389 {
9390         static MonoMethod *ctor;
9391         MonoObject *retval;
9392         void *unboxed, *params [2];
9393
9394         mono_error_init (error);
9395
9396         if (!ctor)
9397                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9398
9399         params [0] = minfo;
9400         params [1] = typedarg;
9401         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9402         return_val_if_nok (error, NULL);
9403
9404         unboxed = mono_object_unbox (retval);
9405
9406         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9407         return_val_if_nok (error, NULL);
9408
9409         return retval;
9410 }
9411
9412 static gboolean
9413 type_is_reference (MonoType *type)
9414 {
9415         switch (type->type) {
9416         case MONO_TYPE_BOOLEAN:
9417         case MONO_TYPE_CHAR:
9418         case MONO_TYPE_U:
9419         case MONO_TYPE_I:
9420         case MONO_TYPE_U1:
9421         case MONO_TYPE_I1:
9422         case MONO_TYPE_U2:
9423         case MONO_TYPE_I2:
9424         case MONO_TYPE_U4:
9425         case MONO_TYPE_I4:
9426         case MONO_TYPE_U8:
9427         case MONO_TYPE_I8:
9428         case MONO_TYPE_R8:
9429         case MONO_TYPE_R4:
9430         case MONO_TYPE_VALUETYPE:
9431                 return FALSE;
9432         default:
9433                 return TRUE;
9434         }
9435 }
9436
9437 static void
9438 free_param_data (MonoMethodSignature *sig, void **params) {
9439         int i;
9440         for (i = 0; i < sig->param_count; ++i) {
9441                 if (!type_is_reference (sig->params [i]))
9442                         g_free (params [i]);
9443         }
9444 }
9445
9446 /*
9447  * Find the field index in the metadata FieldDef table.
9448  */
9449 static guint32
9450 find_field_index (MonoClass *klass, MonoClassField *field) {
9451         int i;
9452
9453         for (i = 0; i < klass->field.count; ++i) {
9454                 if (field == &klass->fields [i])
9455                         return klass->field.first + 1 + i;
9456         }
9457         return 0;
9458 }
9459
9460 /*
9461  * Find the property index in the metadata Property table.
9462  */
9463 static guint32
9464 find_property_index (MonoClass *klass, MonoProperty *property) {
9465         int i;
9466
9467         for (i = 0; i < klass->ext->property.count; ++i) {
9468                 if (property == &klass->ext->properties [i])
9469                         return klass->ext->property.first + 1 + i;
9470         }
9471         return 0;
9472 }
9473
9474 /*
9475  * Find the event index in the metadata Event table.
9476  */
9477 static guint32
9478 find_event_index (MonoClass *klass, MonoEvent *event) {
9479         int i;
9480
9481         for (i = 0; i < klass->ext->event.count; ++i) {
9482                 if (event == &klass->ext->events [i])
9483                         return klass->ext->event.first + 1 + i;
9484         }
9485         return 0;
9486 }
9487
9488 static MonoObject*
9489 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9490 {
9491         const char *p = (const char*)data;
9492         const char *named;
9493         guint32 i, j, num_named;
9494         MonoObject *attr;
9495         void *params_buf [32];
9496         void **params = NULL;
9497         MonoMethodSignature *sig;
9498
9499         mono_error_init (error);
9500
9501         mono_class_init (method->klass);
9502
9503         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9504                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9505                 return NULL;
9506         }
9507
9508         if (len == 0) {
9509                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9510                 if (!mono_error_ok (error)) return NULL;
9511
9512                 mono_runtime_invoke_checked (method, attr, NULL, error);
9513                 if (!mono_error_ok (error))
9514                         return NULL;
9515
9516                 return attr;
9517         }
9518
9519         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9520                 return NULL;
9521
9522         /*g_print ("got attr %s\n", method->klass->name);*/
9523
9524         sig = mono_method_signature (method);
9525         if (sig->param_count < 32) {
9526                 params = params_buf;
9527                 memset (params, 0, sizeof (void*) * sig->param_count);
9528         } else {
9529                 /* Allocate using GC so it gets GC tracking */
9530                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9531         }
9532
9533         /* skip prolog */
9534         p += 2;
9535         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9536                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9537                 if (!mono_error_ok (error))
9538                         goto fail;
9539         }
9540
9541         named = p;
9542         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9543         if (!mono_error_ok (error)) goto fail;
9544
9545         MonoObject *exc = NULL;
9546         mono_runtime_try_invoke (method, attr, params, &exc, error);
9547         if (!mono_error_ok (error))
9548                 goto fail;
9549         if (exc) {
9550                 mono_error_set_exception_instance (error, (MonoException*)exc);
9551                 goto fail;
9552         }
9553
9554         num_named = read16 (named);
9555         named += 2;
9556         for (j = 0; j < num_named; j++) {
9557                 gint name_len;
9558                 char *name, named_type, data_type;
9559                 named_type = *named++;
9560                 data_type = *named++; /* type of data */
9561                 if (data_type == MONO_TYPE_SZARRAY)
9562                         data_type = *named++;
9563                 if (data_type == MONO_TYPE_ENUM) {
9564                         gint type_len;
9565                         char *type_name;
9566                         type_len = mono_metadata_decode_blob_size (named, &named);
9567                         type_name = (char *)g_malloc (type_len + 1);
9568                         memcpy (type_name, named, type_len);
9569                         type_name [type_len] = 0;
9570                         named += type_len;
9571                         /* FIXME: lookup the type and check type consistency */
9572                         g_free (type_name);
9573                 }
9574                 name_len = mono_metadata_decode_blob_size (named, &named);
9575                 name = (char *)g_malloc (name_len + 1);
9576                 memcpy (name, named, name_len);
9577                 name [name_len] = 0;
9578                 named += name_len;
9579                 if (named_type == 0x53) {
9580                         MonoClassField *field;
9581                         void *val;
9582
9583                         /* how this fail is a blackbox */
9584                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9585                         if (!field) {
9586                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9587                                 g_free (name);
9588                                 goto fail;
9589                         }
9590
9591                         val = load_cattr_value (image, field->type, named, &named, error);
9592                         if (!mono_error_ok (error)) {
9593                                 g_free (name);
9594                                 if (!type_is_reference (field->type))
9595                                         g_free (val);
9596                                 goto fail;
9597                         }
9598
9599                         mono_field_set_value (attr, field, val);
9600                         if (!type_is_reference (field->type))
9601                                 g_free (val);
9602                 } else if (named_type == 0x54) {
9603                         MonoProperty *prop;
9604                         void *pparams [1];
9605                         MonoType *prop_type;
9606
9607                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9608
9609                         if (!prop) {
9610                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9611                                 g_free (name);
9612                                 goto fail;
9613                         }
9614
9615                         if (!prop->set) {
9616                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9617                                 g_free (name);
9618                                 goto fail;
9619                         }
9620
9621                         /* can we have more that 1 arg in a custom attr named property? */
9622                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9623                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9624
9625                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9626                         if (!mono_error_ok (error)) {
9627                                 g_free (name);
9628                                 if (!type_is_reference (prop_type))
9629                                         g_free (pparams [0]);
9630                                 goto fail;
9631                         }
9632
9633
9634                         mono_property_set_value_checked (prop, attr, pparams, error);
9635                         if (!type_is_reference (prop_type))
9636                                 g_free (pparams [0]);
9637                         if (!is_ok (error)) {
9638                                 g_free (name);
9639                                 goto fail;
9640                         }
9641                 }
9642                 g_free (name);
9643         }
9644
9645         free_param_data (method->signature, params);
9646         if (params != params_buf)
9647                 mono_gc_free_fixed (params);
9648
9649         return attr;
9650
9651 fail:
9652         free_param_data (method->signature, params);
9653         if (params != params_buf)
9654                 mono_gc_free_fixed (params);
9655         return NULL;
9656 }
9657         
9658 /*
9659  * mono_reflection_create_custom_attr_data_args:
9660  *
9661  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9662  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9663  * NAMED_ARG_INFO will contain information about the named arguments.
9664  */
9665 void
9666 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)
9667 {
9668         MonoArray *typedargs, *namedargs;
9669         MonoClass *attrklass;
9670         MonoDomain *domain;
9671         const char *p = (const char*)data;
9672         const char *named;
9673         guint32 i, j, num_named;
9674         CattrNamedArg *arginfo = NULL;
9675
9676         *typed_args = NULL;
9677         *named_args = NULL;
9678         *named_arg_info = NULL;
9679
9680         mono_error_init (error);
9681
9682         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9683                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9684                 return;
9685         }
9686
9687         mono_class_init (method->klass);
9688         
9689         domain = mono_domain_get ();
9690
9691         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9692                 return;
9693
9694         typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
9695         return_if_nok (error);
9696
9697         /* skip prolog */
9698         p += 2;
9699         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9700                 MonoObject *obj;
9701
9702                 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9703                 return_if_nok (error);
9704                 mono_array_setref (typedargs, i, obj);
9705         }
9706
9707         named = p;
9708         num_named = read16 (named);
9709         namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
9710         return_if_nok (error);
9711         named += 2;
9712         attrklass = method->klass;
9713
9714         arginfo = g_new0 (CattrNamedArg, num_named);
9715         *named_arg_info = arginfo;
9716
9717         for (j = 0; j < num_named; j++) {
9718                 gint name_len;
9719                 char *name, named_type, data_type;
9720                 named_type = *named++;
9721                 data_type = *named++; /* type of data */
9722                 if (data_type == MONO_TYPE_SZARRAY)
9723                         data_type = *named++;
9724                 if (data_type == MONO_TYPE_ENUM) {
9725                         gint type_len;
9726                         char *type_name;
9727                         type_len = mono_metadata_decode_blob_size (named, &named);
9728                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9729                                 goto fail;
9730
9731                         type_name = (char *)g_malloc (type_len + 1);
9732                         memcpy (type_name, named, type_len);
9733                         type_name [type_len] = 0;
9734                         named += type_len;
9735                         /* FIXME: lookup the type and check type consistency */
9736                         g_free (type_name);
9737                 }
9738                 name_len = mono_metadata_decode_blob_size (named, &named);
9739                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9740                         goto fail;
9741                 name = (char *)g_malloc (name_len + 1);
9742                 memcpy (name, named, name_len);
9743                 name [name_len] = 0;
9744                 named += name_len;
9745                 if (named_type == 0x53) {
9746                         MonoObject *obj;
9747                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9748
9749                         if (!field) {
9750                                 g_free (name);
9751                                 goto fail;
9752                         }
9753
9754                         arginfo [j].type = field->type;
9755                         arginfo [j].field = field;
9756
9757                         obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9758                         if (!is_ok (error)) {
9759                                 g_free (name);
9760                                 return;
9761                         }
9762                         mono_array_setref (namedargs, j, obj);
9763
9764                 } else if (named_type == 0x54) {
9765                         MonoObject *obj;
9766                         MonoType *prop_type;
9767                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9768
9769                         if (!prop || !prop->set) {
9770                                 g_free (name);
9771                                 goto fail;
9772                         }
9773
9774                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9775                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9776
9777                         arginfo [j].type = prop_type;
9778                         arginfo [j].prop = prop;
9779
9780                         obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9781                         if (!is_ok (error)) {
9782                                 g_free (name);
9783                                 return;
9784                         }
9785                         mono_array_setref (namedargs, j, obj);
9786                 }
9787                 g_free (name);
9788         }
9789
9790         *typed_args = typedargs;
9791         *named_args = namedargs;
9792         return;
9793 fail:
9794         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9795         g_free (arginfo);
9796         *named_arg_info = NULL;
9797 }
9798
9799 static gboolean
9800 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
9801 {
9802         MonoDomain *domain;
9803         MonoArray *typedargs, *namedargs;
9804         MonoImage *image;
9805         MonoMethod *method;
9806         CattrNamedArg *arginfo = NULL;
9807         int i;
9808
9809         mono_error_init (error);
9810
9811         *ctor_args = NULL;
9812         *named_args = NULL;
9813
9814         if (len == 0)
9815                 return TRUE;
9816
9817         image = assembly->assembly->image;
9818         method = ref_method->method;
9819         domain = mono_object_domain (ref_method);
9820
9821         if (!mono_class_init (method->klass)) {
9822                 mono_error_set_for_class_failure (error, method->klass);
9823                 goto leave;
9824         }
9825
9826         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
9827         if (!is_ok (error))
9828                 goto leave;
9829
9830         if (!typedargs || !namedargs)
9831                 goto leave;
9832
9833         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9834                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9835                 MonoObject *typedarg;
9836
9837                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
9838                 if (!is_ok (error))
9839                         goto leave;
9840                 mono_array_setref (typedargs, i, typedarg);
9841         }
9842
9843         for (i = 0; i < mono_array_length (namedargs); ++i) {
9844                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9845                 MonoObject *typedarg, *namedarg, *minfo;
9846
9847                 if (arginfo [i].prop) {
9848                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
9849                         if (!minfo)
9850                                 goto leave;
9851                 } else {
9852                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
9853                         if (!is_ok (error))
9854                                 goto leave;
9855                 }
9856
9857                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
9858                 if (!is_ok (error))
9859                         goto leave;
9860                 namedarg = create_cattr_named_arg (minfo, typedarg, error);
9861                 if (!is_ok (error))
9862                         goto leave;
9863
9864                 mono_array_setref (namedargs, i, namedarg);
9865         }
9866
9867         *ctor_args = typedargs;
9868         *named_args = namedargs;
9869
9870 leave:
9871         g_free (arginfo);
9872         return mono_error_ok (error);
9873 }
9874
9875 void
9876 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9877 {
9878         MonoError error;
9879         (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
9880         mono_error_set_pending_exception (&error);
9881 }
9882
9883 static MonoObject*
9884 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9885 {
9886         static MonoMethod *ctor;
9887
9888         MonoDomain *domain;
9889         MonoObject *attr;
9890         void *params [4];
9891
9892         mono_error_init (error);
9893
9894         g_assert (image->assembly);
9895
9896         if (!ctor)
9897                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9898
9899         domain = mono_domain_get ();
9900         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9901         return_val_if_nok (error, NULL);
9902         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9903         return_val_if_nok (error, NULL);
9904         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9905         return_val_if_nok (error, NULL);
9906         params [2] = (gpointer)&cattr->data;
9907         params [3] = &cattr->data_size;
9908
9909         mono_runtime_invoke_checked (ctor, attr, params, error);
9910         return_val_if_nok (error, NULL);
9911         return attr;
9912 }
9913
9914 static MonoArray*
9915 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9916 {
9917         MonoArray *result;
9918         MonoObject *attr;
9919         int i, n;
9920
9921         mono_error_init (error);
9922
9923         n = 0;
9924         for (i = 0; i < cinfo->num_attrs; ++i) {
9925                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9926                         n ++;
9927         }
9928
9929         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
9930         return_val_if_nok (error, NULL);
9931         n = 0;
9932         for (i = 0; i < cinfo->num_attrs; ++i) {
9933                 if (!cinfo->attrs [i].ctor) {
9934                         /* The cattr type is not finished yet */
9935                         /* We should include the type name but cinfo doesn't contain it */
9936                         mono_error_set_type_load_name (error, NULL, NULL, "");
9937                         return NULL;
9938                 }
9939                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9940                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9941                         if (!mono_error_ok (error))
9942                                 return result;
9943                         mono_array_setref (result, n, attr);
9944                         n ++;
9945                 }
9946         }
9947         return result;
9948 }
9949
9950 MonoArray*
9951 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9952 {
9953         MonoError error;
9954         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9955         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9956
9957         return result;
9958 }
9959
9960 static MonoArray*
9961 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9962 {
9963         MonoArray *result;
9964         MonoObject *attr;
9965         int i;
9966         
9967         mono_error_init (error);
9968         result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
9969         return_val_if_nok (error, NULL);
9970         for (i = 0; i < cinfo->num_attrs; ++i) {
9971                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9972                 return_val_if_nok (error, NULL);
9973                 mono_array_setref (result, i, attr);
9974         }
9975         return result;
9976 }
9977
9978 /**
9979  * mono_custom_attrs_from_index:
9980  *
9981  * Returns: NULL if no attributes are found or if a loading error occurs.
9982  */
9983 MonoCustomAttrInfo*
9984 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9985 {
9986         MonoError error;
9987         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9988         mono_error_cleanup (&error);
9989         return result;
9990 }
9991 /**
9992  * mono_custom_attrs_from_index_checked:
9993  *
9994  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9995  */
9996 MonoCustomAttrInfo*
9997 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9998 {
9999         guint32 mtoken, i, len;
10000         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
10001         MonoTableInfo *ca;
10002         MonoCustomAttrInfo *ainfo;
10003         GList *tmp, *list = NULL;
10004         const char *data;
10005         MonoCustomAttrEntry* attr;
10006
10007         mono_error_init (error);
10008
10009         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
10010
10011         i = mono_metadata_custom_attrs_from_index (image, idx);
10012         if (!i)
10013                 return NULL;
10014         i --;
10015         while (i < ca->rows) {
10016                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
10017                         break;
10018                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
10019                 ++i;
10020         }
10021         len = g_list_length (list);
10022         if (!len)
10023                 return NULL;
10024         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
10025         ainfo->num_attrs = len;
10026         ainfo->image = image;
10027         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
10028                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
10029                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
10030                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
10031                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
10032                         mtoken |= MONO_TOKEN_METHOD_DEF;
10033                         break;
10034                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
10035                         mtoken |= MONO_TOKEN_MEMBER_REF;
10036                         break;
10037                 default:
10038                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
10039                         break;
10040                 }
10041                 attr = &ainfo->attrs [i - 1];
10042                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
10043                 if (!attr->ctor) {
10044                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
10045                         g_list_free (list);
10046                         g_free (ainfo);
10047                         return NULL;
10048                 }
10049
10050                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
10051                         /*FIXME raising an exception here doesn't make any sense*/
10052                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
10053                         g_list_free (list);
10054                         g_free (ainfo);
10055                         return NULL;
10056                 }
10057                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
10058                 attr->data_size = mono_metadata_decode_value (data, &data);
10059                 attr->data = (guchar*)data;
10060         }
10061         g_list_free (list);
10062
10063         return ainfo;
10064 }
10065
10066 MonoCustomAttrInfo*
10067 mono_custom_attrs_from_method (MonoMethod *method)
10068 {
10069         MonoError error;
10070         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
10071         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10072         return result;
10073 }
10074
10075 MonoCustomAttrInfo*
10076 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
10077 {
10078         guint32 idx;
10079
10080         mono_error_init (error);
10081
10082         /*
10083          * An instantiated method has the same cattrs as the generic method definition.
10084          *
10085          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10086          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10087          */
10088         if (method->is_inflated)
10089                 method = ((MonoMethodInflated *) method)->declaring;
10090         
10091         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
10092                 return lookup_custom_attr (method->klass->image, method);
10093
10094         if (!method->token)
10095                 /* Synthetic methods */
10096                 return NULL;
10097
10098         idx = mono_method_get_index (method);
10099         idx <<= MONO_CUSTOM_ATTR_BITS;
10100         idx |= MONO_CUSTOM_ATTR_METHODDEF;
10101         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
10102 }
10103
10104 MonoCustomAttrInfo*
10105 mono_custom_attrs_from_class (MonoClass *klass)
10106 {
10107         MonoError error;
10108         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
10109         mono_error_cleanup (&error);
10110         return result;
10111 }
10112
10113 MonoCustomAttrInfo*
10114 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
10115 {
10116         guint32 idx;
10117
10118         mono_error_init (error);
10119
10120         if (klass->generic_class)
10121                 klass = klass->generic_class->container_class;
10122
10123         if (image_is_dynamic (klass->image))
10124                 return lookup_custom_attr (klass->image, klass);
10125
10126         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
10127                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
10128                 idx <<= MONO_CUSTOM_ATTR_BITS;
10129                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10130         } else {
10131                 idx = mono_metadata_token_index (klass->type_token);
10132                 idx <<= MONO_CUSTOM_ATTR_BITS;
10133                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10134         }
10135         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10136 }
10137
10138 MonoCustomAttrInfo*
10139 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10140 {
10141         MonoError error;
10142         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10143         mono_error_cleanup (&error);
10144         return result;
10145 }
10146
10147 MonoCustomAttrInfo*
10148 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10149 {
10150         guint32 idx;
10151         
10152         mono_error_init (error);
10153
10154         if (image_is_dynamic (assembly->image))
10155                 return lookup_custom_attr (assembly->image, assembly);
10156         idx = 1; /* there is only one assembly */
10157         idx <<= MONO_CUSTOM_ATTR_BITS;
10158         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10159         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10160 }
10161
10162 static MonoCustomAttrInfo*
10163 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10164 {
10165         guint32 idx;
10166         
10167         if (image_is_dynamic (image))
10168                 return lookup_custom_attr (image, image);
10169         idx = 1; /* there is only one module */
10170         idx <<= MONO_CUSTOM_ATTR_BITS;
10171         idx |= MONO_CUSTOM_ATTR_MODULE;
10172         return mono_custom_attrs_from_index_checked (image, idx, error);
10173 }
10174
10175 MonoCustomAttrInfo*
10176 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10177 {
10178         MonoError error;
10179         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10180         mono_error_cleanup (&error);
10181         return result;
10182 }
10183
10184 MonoCustomAttrInfo*
10185 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10186 {
10187         guint32 idx;
10188         
10189         if (image_is_dynamic (klass->image)) {
10190                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10191                 return lookup_custom_attr (klass->image, property);
10192         }
10193         idx = find_property_index (klass, property);
10194         idx <<= MONO_CUSTOM_ATTR_BITS;
10195         idx |= MONO_CUSTOM_ATTR_PROPERTY;
10196         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10197 }
10198
10199 MonoCustomAttrInfo*
10200 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10201 {
10202         MonoError error;
10203         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10204         mono_error_cleanup (&error);
10205         return result;
10206 }
10207
10208 MonoCustomAttrInfo*
10209 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10210 {
10211         guint32 idx;
10212         
10213         if (image_is_dynamic (klass->image)) {
10214                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10215                 return lookup_custom_attr (klass->image, event);
10216         }
10217         idx = find_event_index (klass, event);
10218         idx <<= MONO_CUSTOM_ATTR_BITS;
10219         idx |= MONO_CUSTOM_ATTR_EVENT;
10220         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10221 }
10222
10223 MonoCustomAttrInfo*
10224 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10225 {
10226         MonoError error;
10227         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10228         mono_error_cleanup (&error);
10229         return result;
10230 }
10231
10232 MonoCustomAttrInfo*
10233 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10234 {
10235         guint32 idx;
10236         mono_error_init (error);
10237
10238         if (image_is_dynamic (klass->image)) {
10239                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10240                 return lookup_custom_attr (klass->image, field);
10241         }
10242         idx = find_field_index (klass, field);
10243         idx <<= MONO_CUSTOM_ATTR_BITS;
10244         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10245         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10246 }
10247
10248 /**
10249  * mono_custom_attrs_from_param:
10250  * @method: handle to the method that we want to retrieve custom parameter information from
10251  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10252  *
10253  * The result must be released with mono_custom_attrs_free().
10254  *
10255  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10256  */
10257 MonoCustomAttrInfo*
10258 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10259 {
10260         MonoError error;
10261         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10262         mono_error_cleanup (&error);
10263         return result;
10264 }
10265
10266 /**
10267  * mono_custom_attrs_from_param_checked:
10268  * @method: handle to the method that we want to retrieve custom parameter information from
10269  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10270  * @error: set on error
10271  *
10272  * The result must be released with mono_custom_attrs_free().
10273  *
10274  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
10275  */
10276 MonoCustomAttrInfo*
10277 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10278 {
10279         MonoTableInfo *ca;
10280         guint32 i, idx, method_index;
10281         guint32 param_list, param_last, param_pos, found;
10282         MonoImage *image;
10283         MonoReflectionMethodAux *aux;
10284
10285         mono_error_init (error);
10286
10287         /*
10288          * An instantiated method has the same cattrs as the generic method definition.
10289          *
10290          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10291          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10292          */
10293         if (method->is_inflated)
10294                 method = ((MonoMethodInflated *) method)->declaring;
10295
10296         if (image_is_dynamic (method->klass->image)) {
10297                 MonoCustomAttrInfo *res, *ainfo;
10298                 int size;
10299
10300                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10301                 if (!aux || !aux->param_cattr)
10302                         return NULL;
10303
10304                 /* Need to copy since it will be freed later */
10305                 ainfo = aux->param_cattr [param];
10306                 if (!ainfo)
10307                         return NULL;
10308                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10309                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10310                 memcpy (res, ainfo, size);
10311                 return res;
10312         }
10313
10314         image = method->klass->image;
10315         method_index = mono_method_get_index (method);
10316         if (!method_index)
10317                 return NULL;
10318         ca = &image->tables [MONO_TABLE_METHOD];
10319
10320         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10321         if (method_index == ca->rows) {
10322                 ca = &image->tables [MONO_TABLE_PARAM];
10323                 param_last = ca->rows + 1;
10324         } else {
10325                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10326                 ca = &image->tables [MONO_TABLE_PARAM];
10327         }
10328         found = FALSE;
10329         for (i = param_list; i < param_last; ++i) {
10330                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10331                 if (param_pos == param) {
10332                         found = TRUE;
10333                         break;
10334                 }
10335         }
10336         if (!found)
10337                 return NULL;
10338         idx = i;
10339         idx <<= MONO_CUSTOM_ATTR_BITS;
10340         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10341         return mono_custom_attrs_from_index_checked (image, idx, error);
10342 }
10343
10344 gboolean
10345 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10346 {
10347         int i;
10348         MonoClass *klass;
10349         for (i = 0; i < ainfo->num_attrs; ++i) {
10350                 klass = ainfo->attrs [i].ctor->klass;
10351                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10352                         return TRUE;
10353         }
10354         return FALSE;
10355 }
10356
10357 MonoObject*
10358 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10359 {
10360         MonoError error;
10361         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10362         mono_error_assert_ok (&error); /*FIXME proper error handling*/
10363         return res;
10364 }
10365
10366 MonoObject*
10367 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10368 {
10369         int i, attr_index;
10370         MonoClass *klass;
10371         MonoArray *attrs;
10372
10373         mono_error_init (error);
10374
10375         attr_index = -1;
10376         for (i = 0; i < ainfo->num_attrs; ++i) {
10377                 klass = ainfo->attrs [i].ctor->klass;
10378                 if (mono_class_has_parent (klass, attr_klass)) {
10379                         attr_index = i;
10380                         break;
10381                 }
10382         }
10383         if (attr_index == -1)
10384                 return NULL;
10385
10386         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10387         if (!mono_error_ok (error))
10388                 return NULL;
10389         return mono_array_get (attrs, MonoObject*, attr_index);
10390 }
10391
10392 /*
10393  * mono_reflection_get_custom_attrs_info:
10394  * @obj: a reflection object handle
10395  *
10396  * Return the custom attribute info for attributes defined for the
10397  * reflection handle @obj. The objects.
10398  *
10399  * FIXME this function leaks like a sieve for SRE objects.
10400  */
10401 MonoCustomAttrInfo*
10402 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10403 {
10404         MonoError error;
10405         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10406         mono_error_assert_ok (&error);
10407         return result;
10408 }
10409
10410 /**
10411  * mono_reflection_get_custom_attrs_info_checked:
10412  * @obj: a reflection object handle
10413  * @error: set on error
10414  *
10415  * Return the custom attribute info for attributes defined for the
10416  * reflection handle @obj. The objects.
10417  *
10418  * On failure returns NULL and sets @error.
10419  *
10420  * FIXME this function leaks like a sieve for SRE objects.
10421  */
10422 MonoCustomAttrInfo*
10423 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10424 {
10425         MonoClass *klass;
10426         MonoCustomAttrInfo *cinfo = NULL;
10427         
10428         mono_error_init (error);
10429
10430         klass = obj->vtable->klass;
10431         if (klass == mono_defaults.runtimetype_class) {
10432                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10433                 return_val_if_nok (error, NULL);
10434                 klass = mono_class_from_mono_type (type);
10435                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10436                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10437                 return_val_if_nok (error, NULL);
10438         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10439                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10440                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10441                 return_val_if_nok (error, NULL);
10442         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10443                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10444                 cinfo = mono_custom_attrs_from_module (module->image, error);
10445                 return_val_if_nok (error, NULL);
10446         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10447                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10448                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10449                 return_val_if_nok (error, NULL);
10450         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10451                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10452                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10453                 return_val_if_nok (error, NULL);
10454         } else if (strcmp ("MonoField", klass->name) == 0) {
10455                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10456                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10457                 return_val_if_nok (error, NULL);
10458         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10459                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10460                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10461                 return_val_if_nok (error, NULL);
10462         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10463                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10464                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10465                 return_val_if_nok (error, NULL);
10466         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10467                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10468                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10469                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10470                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10471                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10472                         return_val_if_nok (error, NULL);
10473                 } else if (is_sr_mono_property (member_class)) {
10474                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10475                         MonoMethod *method;
10476                         if (!(method = prop->property->get))
10477                                 method = prop->property->set;
10478                         g_assert (method);
10479
10480                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10481                         return_val_if_nok (error, NULL);
10482                 } 
10483 #ifndef DISABLE_REFLECTION_EMIT
10484                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10485                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10486                         return_val_if_nok (error, NULL);
10487                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10488                         return_val_if_nok (error, NULL);
10489                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10490                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10491                         MonoMethod *method = NULL;
10492                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10493                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10494                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10495                                 method = ((MonoReflectionMethod *)c->cb)->method;
10496                         else
10497                                 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));
10498
10499                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10500                         return_val_if_nok (error, NULL);
10501                 } 
10502 #endif
10503                 else {
10504                         char *type_name = mono_type_get_full_name (member_class);
10505                         mono_error_set_not_supported (error,
10506                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10507                                                       type_name);
10508                         g_free (type_name);
10509                         return NULL;
10510                 }
10511         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10512                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10513                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10514         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10515                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10516                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10517         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10518                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10519                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10520         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10521                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10522                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10523         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10524                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10525                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10526         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10527                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10528                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10529         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10530                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10531                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10532                 return_val_if_nok (error, NULL);
10533         } else { /* handle other types here... */
10534                 g_error ("get custom attrs not yet supported for %s", klass->name);
10535         }
10536
10537         return cinfo;
10538 }
10539
10540 /*
10541  * mono_reflection_get_custom_attrs_by_type:
10542  * @obj: a reflection object handle
10543  *
10544  * Return an array with all the custom attributes defined of the
10545  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10546  * of that type are returned. The objects are fully build. Return NULL if a loading error
10547  * occurs.
10548  */
10549 MonoArray*
10550 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10551 {
10552         MonoArray *result;
10553         MonoCustomAttrInfo *cinfo;
10554
10555         mono_error_init (error);
10556
10557         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10558         return_val_if_nok (error, NULL);
10559         if (cinfo) {
10560                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10561                 if (!cinfo->cached)
10562                         mono_custom_attrs_free (cinfo);
10563                 if (!result)
10564                         return NULL;
10565         } else {
10566                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
10567         }
10568
10569         return result;
10570 }
10571
10572 /*
10573  * mono_reflection_get_custom_attrs:
10574  * @obj: a reflection object handle
10575  *
10576  * Return an array with all the custom attributes defined of the
10577  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10578  * occurs.
10579  */
10580 MonoArray*
10581 mono_reflection_get_custom_attrs (MonoObject *obj)
10582 {
10583         MonoError error;
10584
10585         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10586 }
10587
10588 /*
10589  * mono_reflection_get_custom_attrs_data:
10590  * @obj: a reflection obj handle
10591  *
10592  * Returns an array of System.Reflection.CustomAttributeData,
10593  * which include information about attributes reflected on
10594  * types loaded using the Reflection Only methods
10595  */
10596 MonoArray*
10597 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10598 {
10599         MonoError error;
10600         MonoArray* result;
10601         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10602         mono_error_cleanup (&error);
10603         return result;
10604 }
10605
10606 /*
10607  * mono_reflection_get_custom_attrs_data_checked:
10608  * @obj: a reflection obj handle
10609  * @error: set on error
10610  *
10611  * Returns an array of System.Reflection.CustomAttributeData,
10612  * which include information about attributes reflected on
10613  * types loaded using the Reflection Only methods
10614  */
10615 MonoArray*
10616 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10617 {
10618         MonoArray *result;
10619         MonoCustomAttrInfo *cinfo;
10620
10621         mono_error_init (error);
10622
10623         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10624         return_val_if_nok (error, NULL);
10625         if (cinfo) {
10626                 result = mono_custom_attrs_data_construct (cinfo, error);
10627                 if (!cinfo->cached)
10628                         mono_custom_attrs_free (cinfo);
10629                 return_val_if_nok (error, NULL);
10630         } else 
10631                 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
10632
10633         return result;
10634 }
10635
10636 static MonoReflectionType*
10637 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10638 {
10639         static MonoMethod *method_get_underlying_system_type = NULL;
10640         MonoReflectionType *rt;
10641         MonoMethod *usertype_method;
10642
10643         mono_error_init (error);
10644
10645         if (!method_get_underlying_system_type)
10646                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10647
10648         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10649
10650         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10651
10652         return rt;
10653 }
10654
10655
10656 static gboolean
10657 is_corlib_type (MonoClass *klass)
10658 {
10659         return klass->image == mono_defaults.corlib;
10660 }
10661
10662 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10663         static MonoClass *cached_class; \
10664         if (cached_class) \
10665                 return cached_class == _class; \
10666         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10667                 cached_class = _class; \
10668                 return TRUE; \
10669         } \
10670         return FALSE; \
10671 } while (0) \
10672
10673
10674 #ifndef DISABLE_REFLECTION_EMIT
10675 static gboolean
10676 is_sre_array (MonoClass *klass)
10677 {
10678         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10679 }
10680
10681 static gboolean
10682 is_sre_byref (MonoClass *klass)
10683 {
10684         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10685 }
10686
10687 static gboolean
10688 is_sre_pointer (MonoClass *klass)
10689 {
10690         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10691 }
10692
10693 static gboolean
10694 is_sre_generic_instance (MonoClass *klass)
10695 {
10696         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10697 }
10698
10699 static gboolean
10700 is_sre_type_builder (MonoClass *klass)
10701 {
10702         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10703 }
10704
10705 static gboolean
10706 is_sre_method_builder (MonoClass *klass)
10707 {
10708         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10709 }
10710
10711 static gboolean
10712 is_sre_ctor_builder (MonoClass *klass)
10713 {
10714         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10715 }
10716
10717 static gboolean
10718 is_sre_field_builder (MonoClass *klass)
10719 {
10720         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10721 }
10722
10723 static gboolean
10724 is_sre_method_on_tb_inst (MonoClass *klass)
10725 {
10726         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10727 }
10728
10729 static gboolean
10730 is_sre_ctor_on_tb_inst (MonoClass *klass)
10731 {
10732         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10733 }
10734
10735 MonoType*
10736 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10737 {
10738         MonoClass *klass;
10739         mono_error_init (error);
10740
10741         if (!ref)
10742                 return NULL;
10743         if (ref->type)
10744                 return ref->type;
10745
10746         if (is_usertype (ref)) {
10747                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10748                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10749                         return NULL;
10750                 if (ref->type)
10751                         return ref->type;
10752         }
10753
10754         klass = mono_object_class (ref);
10755
10756         if (is_sre_array (klass)) {
10757                 MonoType *res;
10758                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10759                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10760                 return_val_if_nok (error, NULL);
10761                 g_assert (base);
10762                 if (sre_array->rank == 0) //single dimentional array
10763                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10764                 else
10765                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10766                 sre_array->type.type = res;
10767                 return res;
10768         } else if (is_sre_byref (klass)) {
10769                 MonoType *res;
10770                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10771                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10772                 return_val_if_nok (error, NULL);
10773                 g_assert (base);
10774                 res = &mono_class_from_mono_type (base)->this_arg;
10775                 sre_byref->type.type = res;
10776                 return res;
10777         } else if (is_sre_pointer (klass)) {
10778                 MonoType *res;
10779                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10780                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10781                 return_val_if_nok (error, NULL);
10782                 g_assert (base);
10783                 res = &mono_ptr_class_get (base)->byval_arg;
10784                 sre_pointer->type.type = res;
10785                 return res;
10786         } else if (is_sre_generic_instance (klass)) {
10787                 MonoType *res, **types;
10788                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10789                 int i, count;
10790
10791                 count = mono_array_length (gclass->type_arguments);
10792                 types = g_new0 (MonoType*, count);
10793                 for (i = 0; i < count; ++i) {
10794                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10795                         types [i] = mono_reflection_type_get_handle (t, error);
10796                         if (!types[i] || !is_ok (error)) {
10797                                 g_free (types);
10798                                 return NULL;
10799                         }
10800                 }
10801
10802                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10803                 g_free (types);
10804                 g_assert (res);
10805                 gclass->type.type = res;
10806                 return res;
10807         }
10808
10809         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10810         return NULL;
10811 }
10812
10813 void
10814 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10815 {
10816         MonoError error;
10817         mono_reflection_type_get_handle (type, &error);
10818         mono_error_set_pending_exception (&error);
10819 }
10820
10821 static gboolean
10822 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10823 {
10824         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10825         MonoClass *klass;
10826
10827         mono_error_init (error);
10828
10829         MonoType *res = mono_reflection_type_get_handle (type, error);
10830
10831         if (!res && is_ok (error)) {
10832                 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10833         }
10834         return_val_if_nok (error, FALSE);
10835
10836         klass = mono_class_from_mono_type (res);
10837
10838         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10839         mono_domain_lock (domain);
10840
10841         if (!image_is_dynamic (klass->image)) {
10842                 mono_class_setup_supertypes (klass);
10843         } else {
10844                 if (!domain->type_hash)
10845                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10846                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10847                 mono_g_hash_table_insert (domain->type_hash, res, type);
10848         }
10849         mono_domain_unlock (domain);
10850         mono_loader_unlock ();
10851
10852         return TRUE;
10853 }
10854
10855 void
10856 mono_reflection_register_with_runtime (MonoReflectionType *type)
10857 {
10858         MonoError error;
10859         (void) reflection_register_with_runtime (type, &error);
10860         mono_error_set_pending_exception (&error);
10861 }
10862
10863 /**
10864  * LOCKING: Assumes the loader lock is held.
10865  */
10866 static MonoMethodSignature*
10867 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10868         MonoMethodSignature *sig;
10869         int count, i;
10870
10871         mono_error_init (error);
10872
10873         count = parameters? mono_array_length (parameters): 0;
10874
10875         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10876         sig->param_count = count;
10877         sig->sentinelpos = -1; /* FIXME */
10878         for (i = 0; i < count; ++i) {
10879                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10880                 if (!is_ok (error)) {
10881                         image_g_free (image, sig);
10882                         return NULL;
10883                 }
10884         }
10885         return sig;
10886 }
10887
10888 /**
10889  * LOCKING: Assumes the loader lock is held.
10890  */
10891 static MonoMethodSignature*
10892 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10893         MonoMethodSignature *sig;
10894
10895         mono_error_init (error);
10896
10897         sig = parameters_to_signature (image, ctor->parameters, error);
10898         return_val_if_nok (error, NULL);
10899         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10900         sig->ret = &mono_defaults.void_class->byval_arg;
10901         return sig;
10902 }
10903
10904 /**
10905  * LOCKING: Assumes the loader lock is held.
10906  */
10907 static MonoMethodSignature*
10908 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10909         MonoMethodSignature *sig;
10910
10911         mono_error_init (error);
10912
10913         sig = parameters_to_signature (image, method->parameters, error);
10914         return_val_if_nok (error, NULL);
10915         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10916         if (method->rtype) {
10917                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10918                 if (!is_ok (error)) {
10919                         image_g_free (image, sig);
10920                         return NULL;
10921                 }
10922         } else {
10923                 sig->ret = &mono_defaults.void_class->byval_arg;
10924         }
10925         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10926         return sig;
10927 }
10928
10929 static MonoMethodSignature*
10930 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10931         MonoMethodSignature *sig;
10932
10933         mono_error_init (error);
10934
10935         sig = parameters_to_signature (NULL, method->parameters, error);
10936         return_val_if_nok (error, NULL);
10937         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10938         if (method->rtype) {
10939                 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10940                 if (!is_ok (error)) {
10941                         g_free (sig);
10942                         return NULL;
10943                 }
10944         } else {
10945                 sig->ret = &mono_defaults.void_class->byval_arg;
10946         }
10947         sig->generic_param_count = 0;
10948         return sig;
10949 }
10950
10951 static void
10952 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10953 {
10954         mono_error_init (error);
10955         MonoClass *klass = mono_object_class (prop);
10956         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10957                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10958                 *name = mono_string_to_utf8_checked (pb->name, error);
10959                 return_if_nok (error);
10960                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10961         } else {
10962                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10963                 *name = g_strdup (p->property->name);
10964                 if (p->property->get)
10965                         *type = mono_method_signature (p->property->get)->ret;
10966                 else
10967                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10968         }
10969 }
10970
10971 static void
10972 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10973 {
10974         mono_error_init (error);
10975         MonoClass *klass = mono_object_class (field);
10976         if (strcmp (klass->name, "FieldBuilder") == 0) {
10977                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10978                 *name = mono_string_to_utf8_checked (fb->name, error);
10979                 return_if_nok (error);
10980                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10981         } else {
10982                 MonoReflectionField *f = (MonoReflectionField *)field;
10983                 *name = g_strdup (mono_field_get_name (f->field));
10984                 *type = f->field->type;
10985         }
10986 }
10987
10988 #else /* DISABLE_REFLECTION_EMIT */
10989
10990 void
10991 mono_reflection_register_with_runtime (MonoReflectionType *type)
10992 {
10993         /* This is empty */
10994 }
10995
10996 static gboolean
10997 is_sre_type_builder (MonoClass *klass)
10998 {
10999         return FALSE;
11000 }
11001
11002 static gboolean
11003 is_sre_generic_instance (MonoClass *klass)
11004 {
11005         return FALSE;
11006 }
11007
11008 static void
11009 init_type_builder_generics (MonoObject *type, MonoError *error)
11010 {
11011         mono_error_init (error);
11012 }
11013
11014 #endif /* !DISABLE_REFLECTION_EMIT */
11015
11016
11017 static gboolean
11018 is_sr_mono_field (MonoClass *klass)
11019 {
11020         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
11021 }
11022
11023 static gboolean
11024 is_sr_mono_property (MonoClass *klass)
11025 {
11026         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
11027 }
11028
11029 static gboolean
11030 is_sr_mono_method (MonoClass *klass)
11031 {
11032         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
11033 }
11034
11035 static gboolean
11036 is_sr_mono_cmethod (MonoClass *klass)
11037 {
11038         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
11039 }
11040
11041 static gboolean
11042 is_sr_mono_generic_method (MonoClass *klass)
11043 {
11044         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
11045 }
11046
11047 static gboolean
11048 is_sr_mono_generic_cmethod (MonoClass *klass)
11049 {
11050         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
11051 }
11052
11053 gboolean
11054 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
11055 {
11056         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
11057 }
11058
11059 static gboolean
11060 is_usertype (MonoReflectionType *ref)
11061 {
11062         MonoClass *klass = mono_object_class (ref);
11063         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
11064 }
11065
11066 static MonoReflectionType*
11067 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
11068 {
11069         mono_error_init (error);
11070         if (!type || type->type)
11071                 return type;
11072
11073         if (is_usertype (type)) {
11074                 type = mono_reflection_type_get_underlying_system_type (type, error);
11075                 return_val_if_nok (error, NULL);
11076                 if (is_usertype (type)) {
11077                         mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
11078                         return NULL;
11079                 }
11080         }
11081
11082         return type;
11083 }
11084 /**
11085  * encode_cattr_value:
11086  * Encode a value in a custom attribute stream of bytes.
11087  * The value to encode is either supplied as an object in argument val
11088  * (valuetypes are boxed), or as a pointer to the data in the
11089  * argument argval.
11090  * @type represents the type of the value
11091  * @buffer is the start of the buffer
11092  * @p the current position in the buffer
11093  * @buflen contains the size of the buffer and is used to return the new buffer size
11094  * if this needs to be realloced.
11095  * @retbuffer and @retp return the start and the position of the buffer
11096  * @error set on error.
11097  */
11098 static void
11099 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
11100 {
11101         MonoTypeEnum simple_type;
11102         
11103         mono_error_init (error);
11104         if ((p-buffer) + 10 >= *buflen) {
11105                 char *newbuf;
11106                 *buflen *= 2;
11107                 newbuf = (char *)g_realloc (buffer, *buflen);
11108                 p = newbuf + (p-buffer);
11109                 buffer = newbuf;
11110         }
11111         if (!argval)
11112                 argval = ((char*)arg + sizeof (MonoObject));
11113         simple_type = type->type;
11114 handle_enum:
11115         switch (simple_type) {
11116         case MONO_TYPE_BOOLEAN:
11117         case MONO_TYPE_U1:
11118         case MONO_TYPE_I1:
11119                 *p++ = *argval;
11120                 break;
11121         case MONO_TYPE_CHAR:
11122         case MONO_TYPE_U2:
11123         case MONO_TYPE_I2:
11124                 swap_with_size (p, argval, 2, 1);
11125                 p += 2;
11126                 break;
11127         case MONO_TYPE_U4:
11128         case MONO_TYPE_I4:
11129         case MONO_TYPE_R4:
11130                 swap_with_size (p, argval, 4, 1);
11131                 p += 4;
11132                 break;
11133         case MONO_TYPE_R8:
11134                 swap_with_size (p, argval, 8, 1);
11135                 p += 8;
11136                 break;
11137         case MONO_TYPE_U8:
11138         case MONO_TYPE_I8:
11139                 swap_with_size (p, argval, 8, 1);
11140                 p += 8;
11141                 break;
11142         case MONO_TYPE_VALUETYPE:
11143                 if (type->data.klass->enumtype) {
11144                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
11145                         goto handle_enum;
11146                 } else {
11147                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11148                 }
11149                 break;
11150         case MONO_TYPE_STRING: {
11151                 char *str;
11152                 guint32 slen;
11153                 if (!arg) {
11154                         *p++ = 0xFF;
11155                         break;
11156                 }
11157                 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
11158                 return_if_nok (error);
11159                 slen = strlen (str);
11160                 if ((p-buffer) + 10 + slen >= *buflen) {
11161                         char *newbuf;
11162                         *buflen *= 2;
11163                         *buflen += slen;
11164                         newbuf = (char *)g_realloc (buffer, *buflen);
11165                         p = newbuf + (p-buffer);
11166                         buffer = newbuf;
11167                 }
11168                 mono_metadata_encode_value (slen, p, &p);
11169                 memcpy (p, str, slen);
11170                 p += slen;
11171                 g_free (str);
11172                 break;
11173         }
11174         case MONO_TYPE_CLASS: {
11175                 char *str;
11176                 guint32 slen;
11177                 MonoType *arg_type;
11178                 if (!arg) {
11179                         *p++ = 0xFF;
11180                         break;
11181                 }
11182 handle_type:
11183                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11184                 return_if_nok (error);
11185
11186                 str = type_get_qualified_name (arg_type, NULL);
11187                 slen = strlen (str);
11188                 if ((p-buffer) + 10 + slen >= *buflen) {
11189                         char *newbuf;
11190                         *buflen *= 2;
11191                         *buflen += slen;
11192                         newbuf = (char *)g_realloc (buffer, *buflen);
11193                         p = newbuf + (p-buffer);
11194                         buffer = newbuf;
11195                 }
11196                 mono_metadata_encode_value (slen, p, &p);
11197                 memcpy (p, str, slen);
11198                 p += slen;
11199                 g_free (str);
11200                 break;
11201         }
11202         case MONO_TYPE_SZARRAY: {
11203                 int len, i;
11204                 MonoClass *eclass, *arg_eclass;
11205
11206                 if (!arg) {
11207                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11208                         break;
11209                 }
11210                 len = mono_array_length ((MonoArray*)arg);
11211                 *p++ = len & 0xff;
11212                 *p++ = (len >> 8) & 0xff;
11213                 *p++ = (len >> 16) & 0xff;
11214                 *p++ = (len >> 24) & 0xff;
11215                 *retp = p;
11216                 *retbuffer = buffer;
11217                 eclass = type->data.klass;
11218                 arg_eclass = mono_object_class (arg)->element_class;
11219
11220                 if (!eclass) {
11221                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11222                         eclass = mono_defaults.object_class;
11223                 }
11224                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11225                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11226                         int elsize = mono_class_array_element_size (arg_eclass);
11227                         for (i = 0; i < len; ++i) {
11228                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11229                                 return_if_nok (error);
11230                                 elptr += elsize;
11231                         }
11232                 } else if (eclass->valuetype && arg_eclass->valuetype) {
11233                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11234                         int elsize = mono_class_array_element_size (eclass);
11235                         for (i = 0; i < len; ++i) {
11236                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11237                                 return_if_nok (error);
11238                                 elptr += elsize;
11239                         }
11240                 } else {
11241                         for (i = 0; i < len; ++i) {
11242                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11243                                 return_if_nok (error);
11244                         }
11245                 }
11246                 break;
11247         }
11248         case MONO_TYPE_OBJECT: {
11249                 MonoClass *klass;
11250                 char *str;
11251                 guint32 slen;
11252
11253                 /*
11254                  * The parameter type is 'object' but the type of the actual
11255                  * argument is not. So we have to add type information to the blob
11256                  * too. This is completely undocumented in the spec.
11257                  */
11258
11259                 if (arg == NULL) {
11260                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
11261                         *p++ = 0xFF;
11262                         break;
11263                 }
11264                 
11265                 klass = mono_object_class (arg);
11266
11267                 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11268                         *p++ = 0x50;
11269                         goto handle_type;
11270                 } else {
11271                         return_if_nok (error);
11272                 }
11273
11274                 if (klass->enumtype) {
11275                         *p++ = 0x55;
11276                 } else if (klass == mono_defaults.string_class) {
11277                         simple_type = MONO_TYPE_STRING;
11278                         *p++ = 0x0E;
11279                         goto handle_enum;
11280                 } else if (klass->rank == 1) {
11281                         *p++ = 0x1D;
11282                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11283                                 /* See Partition II, Appendix B3 */
11284                                 *p++ = 0x51;
11285                         else
11286                                 *p++ = klass->element_class->byval_arg.type;
11287                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11288                         return_if_nok (error);
11289                         break;
11290                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11291                         *p++ = simple_type = klass->byval_arg.type;
11292                         goto handle_enum;
11293                 } else {
11294                         g_error ("unhandled type in custom attr");
11295                 }
11296                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11297                 slen = strlen (str);
11298                 if ((p-buffer) + 10 + slen >= *buflen) {
11299                         char *newbuf;
11300                         *buflen *= 2;
11301                         *buflen += slen;
11302                         newbuf = (char *)g_realloc (buffer, *buflen);
11303                         p = newbuf + (p-buffer);
11304                         buffer = newbuf;
11305                 }
11306                 mono_metadata_encode_value (slen, p, &p);
11307                 memcpy (p, str, slen);
11308                 p += slen;
11309                 g_free (str);
11310                 simple_type = mono_class_enum_basetype (klass)->type;
11311                 goto handle_enum;
11312         }
11313         default:
11314                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11315         }
11316         *retp = p;
11317         *retbuffer = buffer;
11318 }
11319
11320 static void
11321 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11322 {
11323         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11324                 char *str = type_get_qualified_name (type, NULL);
11325                 int slen = strlen (str);
11326
11327                 *p++ = 0x55;
11328                 /*
11329                  * This seems to be optional...
11330                  * *p++ = 0x80;
11331                  */
11332                 mono_metadata_encode_value (slen, p, &p);
11333                 memcpy (p, str, slen);
11334                 p += slen;
11335                 g_free (str);
11336         } else if (type->type == MONO_TYPE_OBJECT) {
11337                 *p++ = 0x51;
11338         } else if (type->type == MONO_TYPE_CLASS) {
11339                 /* it should be a type: encode_cattr_value () has the check */
11340                 *p++ = 0x50;
11341         } else {
11342                 mono_metadata_encode_value (type->type, p, &p);
11343                 if (type->type == MONO_TYPE_SZARRAY)
11344                         /* See the examples in Partition VI, Annex B */
11345                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11346         }
11347
11348         *retp = p;
11349 }
11350
11351 #ifndef DISABLE_REFLECTION_EMIT
11352 static void
11353 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11354 {
11355         int len;
11356
11357         mono_error_init (error);
11358
11359         /* Preallocate a large enough buffer */
11360         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11361                 char *str = type_get_qualified_name (type, NULL);
11362                 len = strlen (str);
11363                 g_free (str);
11364         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11365                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11366                 len = strlen (str);
11367                 g_free (str);
11368         } else {
11369                 len = 0;
11370         }
11371         len += strlen (name);
11372
11373         if ((p-buffer) + 20 + len >= *buflen) {
11374                 char *newbuf;
11375                 *buflen *= 2;
11376                 *buflen += len;
11377                 newbuf = (char *)g_realloc (buffer, *buflen);
11378                 p = newbuf + (p-buffer);
11379                 buffer = newbuf;
11380         }
11381
11382         encode_field_or_prop_type (type, p, &p);
11383
11384         len = strlen (name);
11385         mono_metadata_encode_value (len, p, &p);
11386         memcpy (p, name, len);
11387         p += len;
11388         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11389         return_if_nok (error);
11390         *retp = p;
11391         *retbuffer = buffer;
11392 }
11393
11394 /**
11395  * mono_reflection_get_custom_attrs_blob:
11396  * @ctor: custom attribute constructor
11397  * @ctorArgs: arguments o the constructor
11398  * @properties:
11399  * @propValues:
11400  * @fields:
11401  * @fieldValues:
11402  * 
11403  * Creates the blob of data that needs to be saved in the metadata and that represents
11404  * the custom attributed described by @ctor, @ctorArgs etc.
11405  * Returns: a Byte array representing the blob of data.
11406  */
11407 MonoArray*
11408 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11409 {
11410         MonoError error;
11411         MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11412         mono_error_cleanup (&error);
11413         return result;
11414 }
11415
11416 /**
11417  * mono_reflection_get_custom_attrs_blob_checked:
11418  * @ctor: custom attribute constructor
11419  * @ctorArgs: arguments o the constructor
11420  * @properties:
11421  * @propValues:
11422  * @fields:
11423  * @fieldValues:
11424  * @error: set on error
11425  * 
11426  * Creates the blob of data that needs to be saved in the metadata and that represents
11427  * the custom attributed described by @ctor, @ctorArgs etc.
11428  * Returns: a Byte array representing the blob of data.  On failure returns NULL and sets @error.
11429  */
11430 MonoArray*
11431 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error) 
11432 {
11433         MonoArray *result = NULL;
11434         MonoMethodSignature *sig;
11435         MonoObject *arg;
11436         char *buffer, *p;
11437         guint32 buflen, i;
11438
11439         mono_error_init (error);
11440
11441         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11442                 /* sig is freed later so allocate it in the heap */
11443                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11444                 if (!is_ok (error)) {
11445                         g_free (sig);
11446                         return NULL;
11447                 }
11448         } else {
11449                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11450         }
11451
11452         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11453         buflen = 256;
11454         p = buffer = (char *)g_malloc (buflen);
11455         /* write the prolog */
11456         *p++ = 1;
11457         *p++ = 0;
11458         for (i = 0; i < sig->param_count; ++i) {
11459                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11460                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11461                 if (!is_ok (error)) goto leave;
11462         }
11463         i = 0;
11464         if (properties)
11465                 i += mono_array_length (properties);
11466         if (fields)
11467                 i += mono_array_length (fields);
11468         *p++ = i & 0xff;
11469         *p++ = (i >> 8) & 0xff;
11470         if (properties) {
11471                 MonoObject *prop;
11472                 for (i = 0; i < mono_array_length (properties); ++i) {
11473                         MonoType *ptype;
11474                         char *pname;
11475
11476                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11477                         get_prop_name_and_type (prop, &pname, &ptype, error);
11478                         if (!is_ok (error)) goto leave;
11479                         *p++ = 0x54; /* PROPERTY signature */
11480                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11481                         g_free (pname);
11482                         if (!is_ok (error)) goto leave;
11483                 }
11484         }
11485
11486         if (fields) {
11487                 MonoObject *field;
11488                 for (i = 0; i < mono_array_length (fields); ++i) {
11489                         MonoType *ftype;
11490                         char *fname;
11491
11492                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11493                         get_field_name_and_type (field, &fname, &ftype, error);
11494                         if (!is_ok (error)) goto leave;
11495                         *p++ = 0x53; /* FIELD signature */
11496                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11497                         g_free (fname);
11498                         if (!is_ok (error)) goto leave;
11499                 }
11500         }
11501
11502         g_assert (p - buffer <= buflen);
11503         buflen = p - buffer;
11504         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
11505         if (!is_ok (error))
11506                 goto leave;
11507         p = mono_array_addr (result, char, 0);
11508         memcpy (p, buffer, buflen);
11509 leave:
11510         g_free (buffer);
11511         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11512                 g_free (sig);
11513         return result;
11514 }
11515
11516 /**
11517  * reflection_setup_internal_class:
11518  * @tb: a TypeBuilder object
11519  * @error: set on error
11520  *
11521  * Creates a MonoClass that represents the TypeBuilder.
11522  * This is a trick that lets us simplify a lot of reflection code
11523  * (and will allow us to support Build and Run assemblies easier).
11524  *
11525  * Returns TRUE on success. On failure, returns FALSE and sets @error.
11526  */
11527 static gboolean
11528 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11529 {
11530         MonoClass *klass, *parent;
11531
11532         mono_error_init (error);
11533         RESOLVE_TYPE (tb->parent, error);
11534         return_val_if_nok (error, FALSE);
11535
11536         mono_loader_lock ();
11537
11538         if (tb->parent) {
11539                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11540                 if (!is_ok (error)) {
11541                         mono_loader_unlock ();
11542                         return FALSE;
11543                 }
11544                 /* check so we can compile corlib correctly */
11545                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11546                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11547                         parent = parent_type->data.klass;
11548                 } else {
11549                         parent = mono_class_from_mono_type (parent_type);
11550                 }
11551         } else {
11552                 parent = NULL;
11553         }
11554         
11555         /* the type has already being created: it means we just have to change the parent */
11556         if (tb->type.type) {
11557                 klass = mono_class_from_mono_type (tb->type.type);
11558                 klass->parent = NULL;
11559                 /* fool mono_class_setup_parent */
11560                 klass->supertypes = NULL;
11561                 mono_class_setup_parent (klass, parent);
11562                 mono_class_setup_mono_type (klass);
11563                 mono_loader_unlock ();
11564                 return TRUE;
11565         }
11566
11567         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11568
11569         klass->image = &tb->module->dynamic_image->image;
11570
11571         klass->inited = 1; /* we lie to the runtime */
11572         klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11573         if (!is_ok (error))
11574                 goto failure;
11575         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11576         if (!is_ok (error))
11577                 goto failure;
11578         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11579         klass->flags = tb->attrs;
11580         
11581         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11582
11583         klass->element_class = klass;
11584
11585         if (mono_class_get_ref_info (klass) == NULL) {
11586
11587                 mono_class_set_ref_info (klass, tb);
11588
11589                 /* Put into cache so mono_class_get_checked () will find it.
11590                 Skip nested types as those should not be available on the global scope. */
11591                 if (!tb->nesting_type)
11592                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11593
11594                 /*
11595                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11596                 by performing a mono_class_get which does the full resolution.
11597
11598                 Working around this semantics would require us to write a lot of code for no clear advantage.
11599                 */
11600                 mono_image_append_class_to_reflection_info_set (klass);
11601         } else {
11602                 g_assert (mono_class_get_ref_info (klass) == tb);
11603         }
11604
11605         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11606
11607         if (parent != NULL) {
11608                 mono_class_setup_parent (klass, parent);
11609         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11610                 const char *old_n = klass->name;
11611                 /* trick to get relative numbering right when compiling corlib */
11612                 klass->name = "BuildingObject";
11613                 mono_class_setup_parent (klass, mono_defaults.object_class);
11614                 klass->name = old_n;
11615         }
11616
11617         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11618                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11619                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11620                 klass->instance_size = sizeof (MonoObject);
11621                 klass->size_inited = 1;
11622                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11623         }
11624
11625         mono_class_setup_mono_type (klass);
11626
11627         mono_class_setup_supertypes (klass);
11628
11629         /*
11630          * FIXME: handle interfaces.
11631          */
11632
11633         tb->type.type = &klass->byval_arg;
11634
11635         if (tb->nesting_type) {
11636                 g_assert (tb->nesting_type->type);
11637                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11638                 if (!is_ok (error)) goto failure;
11639                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11640         }
11641
11642         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11643
11644         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11645         
11646         mono_loader_unlock ();
11647         return TRUE;
11648
11649 failure:
11650         mono_loader_unlock ();
11651         return FALSE;
11652 }
11653
11654 /**
11655  * mono_reflection_setup_internal_class:
11656  * @tb: a TypeBuilder object
11657  *
11658  * (icall)
11659  * Creates a MonoClass that represents the TypeBuilder.
11660  * This is a trick that lets us simplify a lot of reflection code
11661  * (and will allow us to support Build and Run assemblies easier).
11662  *
11663  */
11664 void
11665 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11666 {
11667         MonoError error;
11668         (void) reflection_setup_internal_class (tb, &error);
11669         mono_error_set_pending_exception (&error);
11670 }
11671
11672 /*
11673  * mono_reflection_setup_generic_class:
11674  * @tb: a TypeBuilder object
11675  *
11676  * Setup the generic class before adding the first generic parameter.
11677  */
11678 void
11679 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11680 {
11681 }
11682
11683 /**
11684  * mono_reflection_create_generic_class:
11685  * @tb: a TypeBuilder object
11686  * @error: set on error
11687  *
11688  * Creates the generic class after all generic parameters have been added.
11689  * On success returns TRUE, on failure returns FALSE and sets @error.
11690  * 
11691  */
11692 gboolean
11693 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11694 {
11695
11696         MonoClass *klass;
11697         int count, i;
11698
11699         mono_error_init (error);
11700
11701         klass = mono_class_from_mono_type (tb->type.type);
11702
11703         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11704
11705         if (klass->generic_container || (count == 0))
11706                 return TRUE;
11707
11708         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11709
11710         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11711
11712         klass->generic_container->owner.klass = klass;
11713         klass->generic_container->type_argc = count;
11714         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11715
11716         klass->is_generic = 1;
11717
11718         for (i = 0; i < count; i++) {
11719                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11720                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
11721                 return_val_if_nok (error, FALSE);
11722                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11723                 klass->generic_container->type_params [i] = *param;
11724                 /*Make sure we are a diferent type instance */
11725                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11726                 klass->generic_container->type_params [i].info.pklass = NULL;
11727                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11728
11729                 g_assert (klass->generic_container->type_params [i].param.owner);
11730         }
11731
11732         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11733         return TRUE;
11734 }
11735
11736 /**
11737  * reflection_create_internal_class:
11738  * @tb: a TypeBuilder object
11739  * @error: set on error
11740  *
11741  * Actually create the MonoClass that is associated with the TypeBuilder.
11742  * On success returns TRUE, on failure returns FALSE and sets @error.
11743  *
11744  */
11745 static gboolean
11746 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11747 {
11748
11749         MonoClass *klass;
11750
11751         mono_error_init (error);
11752         klass = mono_class_from_mono_type (tb->type.type);
11753
11754         mono_loader_lock ();
11755         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11756                 MonoReflectionFieldBuilder *fb;
11757                 MonoClass *ec;
11758                 MonoType *enum_basetype;
11759
11760                 g_assert (tb->fields != NULL);
11761                 g_assert (mono_array_length (tb->fields) >= 1);
11762
11763                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11764
11765                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11766                 if (!is_ok (error)) {
11767                         mono_loader_unlock ();
11768                         return FALSE;
11769                 }
11770                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11771                         mono_loader_unlock ();
11772                         return TRUE;
11773                 }
11774
11775                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11776                 if (!is_ok (error)) {
11777                         mono_loader_unlock ();
11778                         return FALSE;
11779                 }
11780                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11781                 if (!klass->element_class)
11782                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11783
11784                 /*
11785                  * get the element_class from the current corlib.
11786                  */
11787                 ec = default_class_from_mono_type (enum_basetype);
11788                 klass->instance_size = ec->instance_size;
11789                 klass->size_inited = 1;
11790                 /* 
11791                  * this is almost safe to do with enums and it's needed to be able
11792                  * to create objects of the enum type (for use in SetConstant).
11793                  */
11794                 /* FIXME: Does this mean enums can't have method overrides ? */
11795                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11796         }
11797         mono_loader_unlock ();
11798         return TRUE;
11799 }
11800
11801 /**
11802  * mono_reflection_create_internal_class:
11803  * @tb: a TypeBuilder object
11804  *
11805  * (icall)
11806  * Actually create the MonoClass that is associated with the TypeBuilder.
11807  */
11808 void
11809 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11810 {
11811         MonoError error;
11812         (void) reflection_create_internal_class (tb, &error);
11813         mono_error_set_pending_exception (&error);
11814 }
11815
11816 static MonoMarshalSpec*
11817 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11818                                 MonoReflectionMarshal *minfo, MonoError *error)
11819 {
11820         MonoMarshalSpec *res;
11821
11822         mono_error_init (error);
11823
11824         res = image_g_new0 (image, MonoMarshalSpec, 1);
11825         res->native = (MonoMarshalNative)minfo->type;
11826
11827         switch (minfo->type) {
11828         case MONO_NATIVE_LPARRAY:
11829                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11830                 if (minfo->has_size) {
11831                         res->data.array_data.param_num = minfo->param_num;
11832                         res->data.array_data.num_elem = minfo->count;
11833                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11834                 }
11835                 else {
11836                         res->data.array_data.param_num = -1;
11837                         res->data.array_data.num_elem = -1;
11838                         res->data.array_data.elem_mult = -1;
11839                 }
11840                 break;
11841
11842         case MONO_NATIVE_BYVALTSTR:
11843         case MONO_NATIVE_BYVALARRAY:
11844                 res->data.array_data.num_elem = minfo->count;
11845                 break;
11846
11847         case MONO_NATIVE_CUSTOM:
11848                 if (minfo->marshaltyperef) {
11849                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11850                         if (!is_ok (error)) {
11851                                 image_g_free (image, res);
11852                                 return NULL;
11853                         }
11854                         res->data.custom_data.custom_name =
11855                                 type_get_fully_qualified_name (marshaltyperef);
11856                 }
11857                 if (minfo->mcookie) {
11858                         res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
11859                         if (!is_ok (error)) {
11860                                 image_g_free (image, res);
11861                                 return NULL;
11862                         }
11863                 }
11864                 break;
11865
11866         default:
11867                 break;
11868         }
11869
11870         return res;
11871 }
11872 #endif /* !DISABLE_REFLECTION_EMIT */
11873
11874 MonoReflectionMarshalAsAttribute*
11875 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11876                                                         MonoMarshalSpec *spec, MonoError *error)
11877 {
11878         MonoReflectionType *rt;
11879         MonoReflectionMarshalAsAttribute *minfo;
11880         MonoType *mtype;
11881
11882         mono_error_init (error);
11883         
11884         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11885         if (!minfo)
11886                 return NULL;
11887         minfo->utype = spec->native;
11888
11889         switch (minfo->utype) {
11890         case MONO_NATIVE_LPARRAY:
11891                 minfo->array_subtype = spec->data.array_data.elem_type;
11892                 minfo->size_const = spec->data.array_data.num_elem;
11893                 if (spec->data.array_data.param_num != -1)
11894                         minfo->size_param_index = spec->data.array_data.param_num;
11895                 break;
11896
11897         case MONO_NATIVE_BYVALTSTR:
11898         case MONO_NATIVE_BYVALARRAY:
11899                 minfo->size_const = spec->data.array_data.num_elem;
11900                 break;
11901
11902         case MONO_NATIVE_CUSTOM:
11903                 if (spec->data.custom_data.custom_name) {
11904                         mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11905                         return_val_if_nok  (error, NULL);
11906
11907                         if (mtype) {
11908                                 rt = mono_type_get_object_checked (domain, mtype, error);
11909                                 if (!rt)
11910                                         return NULL;
11911
11912                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11913                         }
11914
11915                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11916                 }
11917                 if (spec->data.custom_data.cookie)
11918                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11919                 break;
11920
11921         default:
11922                 break;
11923         }
11924
11925         return minfo;
11926 }
11927
11928 #ifndef DISABLE_REFLECTION_EMIT
11929 static MonoMethod*
11930 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11931                                          ReflectionMethodBuilder *rmb,
11932                                          MonoMethodSignature *sig,
11933                                          MonoError *error)
11934 {
11935         MonoMethod *m;
11936         MonoMethodWrapper *wrapperm;
11937         MonoMarshalSpec **specs;
11938         MonoReflectionMethodAux *method_aux;
11939         MonoImage *image;
11940         gboolean dynamic;
11941         int i;
11942
11943         mono_error_init (error);
11944         /*
11945          * Methods created using a MethodBuilder should have their memory allocated
11946          * inside the image mempool, while dynamic methods should have their memory
11947          * malloc'd.
11948          */
11949         dynamic = rmb->refs != NULL;
11950         image = dynamic ? NULL : klass->image;
11951
11952         if (!dynamic)
11953                 g_assert (!klass->generic_class);
11954
11955         mono_loader_lock ();
11956
11957         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11958                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11959                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11960         else
11961                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11962
11963         wrapperm = (MonoMethodWrapper*)m;
11964
11965         m->dynamic = dynamic;
11966         m->slot = -1;
11967         m->flags = rmb->attrs;
11968         m->iflags = rmb->iattrs;
11969         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11970         m->klass = klass;
11971         m->signature = sig;
11972         m->sre_method = TRUE;
11973         m->skip_visibility = rmb->skip_visibility;
11974         if (rmb->table_idx)
11975                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11976
11977         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11978                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11979                         m->string_ctor = 1;
11980
11981                 m->signature->pinvoke = 1;
11982         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11983                 m->signature->pinvoke = 1;
11984
11985                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11986
11987                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
11988                 mono_error_assert_ok (error);
11989                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
11990                 mono_error_assert_ok (error);
11991                 
11992                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11993
11994                 if (image_is_dynamic (klass->image))
11995                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11996
11997                 mono_loader_unlock ();
11998
11999                 return m;
12000         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
12001                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
12002                 MonoMethodHeader *header;
12003                 guint32 code_size;
12004                 gint32 max_stack, i;
12005                 gint32 num_locals = 0;
12006                 gint32 num_clauses = 0;
12007                 guint8 *code;
12008
12009                 if (rmb->ilgen) {
12010                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
12011                         code_size = rmb->ilgen->code_len;
12012                         max_stack = rmb->ilgen->max_stack;
12013                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
12014                         if (rmb->ilgen->ex_handlers)
12015                                 num_clauses = method_count_clauses (rmb->ilgen);
12016                 } else {
12017                         if (rmb->code) {
12018                                 code = mono_array_addr (rmb->code, guint8, 0);
12019                                 code_size = mono_array_length (rmb->code);
12020                                 /* we probably need to run a verifier on the code... */
12021                                 max_stack = 8; 
12022                         }
12023                         else {
12024                                 code = NULL;
12025                                 code_size = 0;
12026                                 max_stack = 8;
12027                         }
12028                 }
12029
12030                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
12031                 header->code_size = code_size;
12032                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
12033                 memcpy ((char*)header->code, code, code_size);
12034                 header->max_stack = max_stack;
12035                 header->init_locals = rmb->init_locals;
12036                 header->num_locals = num_locals;
12037
12038                 for (i = 0; i < num_locals; ++i) {
12039                         MonoReflectionLocalBuilder *lb = 
12040                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
12041
12042                         header->locals [i] = image_g_new0 (image, MonoType, 1);
12043                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
12044                         mono_error_assert_ok (error);
12045                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
12046                 }
12047
12048                 header->num_clauses = num_clauses;
12049                 if (num_clauses) {
12050                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
12051                                                                  rmb->ilgen, num_clauses, error);
12052                         mono_error_assert_ok (error);
12053                 }
12054
12055                 wrapperm->header = header;
12056         }
12057
12058         if (rmb->generic_params) {
12059                 int count = mono_array_length (rmb->generic_params);
12060                 MonoGenericContainer *container = rmb->generic_container;
12061
12062                 g_assert (container);
12063
12064                 container->type_argc = count;
12065                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
12066                 container->owner.method = m;
12067                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
12068
12069                 m->is_generic = TRUE;
12070                 mono_method_set_generic_container (m, container);
12071
12072                 for (i = 0; i < count; i++) {
12073                         MonoReflectionGenericParam *gp =
12074                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
12075                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
12076                         mono_error_assert_ok (error);
12077                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
12078                         container->type_params [i] = *param;
12079                 }
12080
12081                 /*
12082                  * The method signature might have pointers to generic parameters that belong to other methods.
12083                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
12084                  * generic parameters.
12085                  */
12086                 for (i = 0; i < m->signature->param_count; ++i) {
12087                         MonoType *t = m->signature->params [i];
12088                         if (t->type == MONO_TYPE_MVAR) {
12089                                 MonoGenericParam *gparam =  t->data.generic_param;
12090                                 if (gparam->num < count) {
12091                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
12092                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
12093                                 }
12094
12095                         }
12096                 }
12097
12098                 if (klass->generic_container) {
12099                         container->parent = klass->generic_container;
12100                         container->context.class_inst = klass->generic_container->context.class_inst;
12101                 }
12102                 container->context.method_inst = mono_get_shared_generic_inst (container);
12103         }
12104
12105         if (rmb->refs) {
12106                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
12107                 int i;
12108                 void **data;
12109
12110                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
12111
12112                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
12113                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
12114                 for (i = 0; i < rmb->nrefs; ++i)
12115                         data [i + 1] = rmb->refs [i];
12116         }
12117
12118         method_aux = NULL;
12119
12120         /* Parameter info */
12121         if (rmb->pinfo) {
12122                 if (!method_aux)
12123                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12124                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
12125                 for (i = 0; i <= m->signature->param_count; ++i) {
12126                         MonoReflectionParamBuilder *pb;
12127                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12128                                 if ((i > 0) && (pb->attrs)) {
12129                                         /* Make a copy since it might point to a shared type structure */
12130                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
12131                                         m->signature->params [i - 1]->attrs = pb->attrs;
12132                                 }
12133
12134                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
12135                                         MonoDynamicImage *assembly;
12136                                         guint32 idx, len;
12137                                         MonoTypeEnum def_type;
12138                                         char *p;
12139                                         const char *p2;
12140
12141                                         if (!method_aux->param_defaults) {
12142                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12143                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12144                                         }
12145                                         assembly = (MonoDynamicImage*)klass->image;
12146                                         idx = encode_constant (assembly, pb->def_value, &def_type);
12147                                         /* Copy the data from the blob since it might get realloc-ed */
12148                                         p = assembly->blob.data + idx;
12149                                         len = mono_metadata_decode_blob_size (p, &p2);
12150                                         len += p2 - p;
12151                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12152                                         method_aux->param_default_types [i] = def_type;
12153                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12154                                 }
12155
12156                                 if (pb->name) {
12157                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
12158                                         mono_error_assert_ok (error);
12159                                 }
12160                                 if (pb->cattrs) {
12161                                         if (!method_aux->param_cattr)
12162                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12163                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12164                                 }
12165                         }
12166                 }
12167         }
12168
12169         /* Parameter marshalling */
12170         specs = NULL;
12171         if (rmb->pinfo)         
12172                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12173                         MonoReflectionParamBuilder *pb;
12174                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12175                                 if (pb->marshal_info) {
12176                                         if (specs == NULL)
12177                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12178                                         specs [pb->position] = 
12179                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
12180                                         if (!is_ok (error)) {
12181                                                 mono_loader_unlock ();
12182                                                 image_g_free (image, specs);
12183                                                 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
12184                                                 return NULL;
12185                                         }
12186                                 }
12187                         }
12188                 }
12189         if (specs != NULL) {
12190                 if (!method_aux)
12191                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12192                 method_aux->param_marshall = specs;
12193         }
12194
12195         if (image_is_dynamic (klass->image) && method_aux)
12196                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12197
12198         mono_loader_unlock ();
12199
12200         return m;
12201 }       
12202
12203 static MonoMethod*
12204 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12205 {
12206         ReflectionMethodBuilder rmb;
12207         MonoMethodSignature *sig;
12208
12209         mono_loader_lock ();
12210         g_assert (klass->image != NULL);
12211         sig = ctor_builder_to_signature (klass->image, mb, error);
12212         mono_loader_unlock ();
12213         return_val_if_nok (error, NULL);
12214
12215         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12216                 return NULL;
12217
12218         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12219         return_val_if_nok (error, NULL);
12220         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12221
12222         /* If we are in a generic class, we might be called multiple times from inflate_method */
12223         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12224                 /* ilgen is no longer needed */
12225                 mb->ilgen = NULL;
12226         }
12227
12228         return mb->mhandle;
12229 }
12230
12231 static MonoMethod*
12232 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12233 {
12234         ReflectionMethodBuilder rmb;
12235         MonoMethodSignature *sig;
12236
12237         mono_error_init (error);
12238
12239         mono_loader_lock ();
12240         g_assert (klass->image != NULL);
12241         sig = method_builder_to_signature (klass->image, mb, error);
12242         mono_loader_unlock ();
12243         return_val_if_nok (error, NULL);
12244
12245         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12246                 return NULL;
12247
12248         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12249         return_val_if_nok (error, NULL);
12250         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12251
12252         /* If we are in a generic class, we might be called multiple times from inflate_method */
12253         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12254                 /* ilgen is no longer needed */
12255                 mb->ilgen = NULL;
12256         }
12257         return mb->mhandle;
12258 }
12259
12260 static MonoClassField*
12261 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12262 {
12263         MonoClassField *field;
12264         MonoType *custom;
12265
12266         mono_error_init (error);
12267
12268         field = g_new0 (MonoClassField, 1);
12269
12270         field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12271         mono_error_assert_ok (error);
12272         if (fb->attrs || fb->modreq || fb->modopt) {
12273                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12274                 if (!is_ok (error)) {
12275                         g_free (field);
12276                         return NULL;
12277                 }
12278                 field->type = mono_metadata_type_dup (NULL, type);
12279                 field->type->attrs = fb->attrs;
12280
12281                 g_assert (image_is_dynamic (klass->image));
12282                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12283                 g_free (field->type);
12284                 if (!is_ok (error)) {
12285                         g_free (field);
12286                         return NULL;
12287                 }
12288                 field->type = mono_metadata_type_dup (klass->image, custom);
12289                 g_free (custom);
12290         } else {
12291                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12292                 if (!is_ok (error)) {
12293                         g_free (field);
12294                         return NULL;
12295                 }
12296         }
12297         if (fb->offset != -1)
12298                 field->offset = fb->offset;
12299         field->parent = klass;
12300         mono_save_custom_attrs (klass->image, field, fb->cattrs);
12301
12302         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12303
12304         return field;
12305 }
12306 #endif
12307
12308 /**
12309  * mono_reflection_bind_generic_parameters:
12310  * @type: a managed type object (which should be some kind of generic (instance? definition?))
12311  * @type_args: the number of type arguments to bind
12312  * @types: array of type arguments
12313  * @error: set on error
12314  *
12315  * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12316  * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
12317  */
12318 MonoType*
12319 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12320 {
12321         MonoClass *klass;
12322         MonoReflectionTypeBuilder *tb = NULL;
12323         gboolean is_dynamic = FALSE;
12324         MonoClass *geninst;
12325
12326         mono_error_init (error);
12327         
12328         mono_loader_lock ();
12329
12330         if (is_sre_type_builder (mono_object_class (type))) {
12331                 tb = (MonoReflectionTypeBuilder *) type;
12332
12333                 is_dynamic = TRUE;
12334         } else if (is_sre_generic_instance (mono_object_class (type))) {
12335                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12336                 MonoReflectionType *gtd = rgi->generic_type;
12337
12338                 if (is_sre_type_builder (mono_object_class (gtd))) {
12339                         tb = (MonoReflectionTypeBuilder *)gtd;
12340                         is_dynamic = TRUE;
12341                 }
12342         }
12343
12344         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12345         if (tb && tb->generic_container) {
12346                 if (!mono_reflection_create_generic_class (tb, error)) {
12347                         mono_loader_unlock ();
12348                         return NULL;
12349                 }
12350         }
12351
12352         MonoType *t = mono_reflection_type_get_handle (type, error);
12353         if (!is_ok (error)) {
12354                 mono_loader_unlock ();
12355                 return NULL;
12356         }
12357
12358         klass = mono_class_from_mono_type (t);
12359         if (!klass->generic_container) {
12360                 mono_loader_unlock ();
12361                 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12362                 return NULL;
12363         }
12364
12365         if (klass->wastypebuilder) {
12366                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12367
12368                 is_dynamic = TRUE;
12369         }
12370
12371         mono_loader_unlock ();
12372
12373         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12374
12375         return &geninst->byval_arg;
12376 }
12377
12378 MonoClass*
12379 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12380 {
12381         MonoGenericClass *gclass;
12382         MonoGenericInst *inst;
12383
12384         g_assert (klass->generic_container);
12385
12386         inst = mono_metadata_get_generic_inst (type_argc, types);
12387         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12388
12389         return mono_generic_class_get_class (gclass);
12390 }
12391
12392 static MonoReflectionMethod*
12393 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
12394 {
12395         MonoClass *klass;
12396         MonoMethod *method, *inflated;
12397         MonoMethodInflated *imethod;
12398         MonoGenericContext tmp_context;
12399         MonoGenericInst *ginst;
12400         MonoType **type_argv;
12401         int count, i;
12402
12403         mono_error_init (error);
12404
12405         /*FIXME but this no longer should happen*/
12406         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12407 #ifndef DISABLE_REFLECTION_EMIT
12408                 MonoReflectionMethodBuilder *mb = NULL;
12409                 MonoType *tb;
12410                 MonoClass *klass;
12411
12412                 mb = (MonoReflectionMethodBuilder *) rmethod;
12413                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
12414                 return_val_if_nok (error, NULL);
12415                 klass = mono_class_from_mono_type (tb);
12416
12417                 method = methodbuilder_to_mono_method (klass, mb, error);
12418                 return_val_if_nok (error, NULL);
12419 #else
12420                 g_assert_not_reached ();
12421                 method = NULL;
12422 #endif
12423         } else {
12424                 method = rmethod->method;
12425         }
12426
12427         klass = method->klass;
12428
12429         if (method->is_inflated)
12430                 method = ((MonoMethodInflated *) method)->declaring;
12431
12432         count = mono_method_signature (method)->generic_param_count;
12433         if (count != mono_array_length (types))
12434                 return NULL;
12435
12436         type_argv = g_new0 (MonoType *, count);
12437         for (i = 0; i < count; i++) {
12438                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12439                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
12440                 if (!is_ok (error)) {
12441                         g_free (type_argv);
12442                         return NULL;
12443                 }
12444         }
12445         ginst = mono_metadata_get_generic_inst (count, type_argv);
12446         g_free (type_argv);
12447
12448         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12449         tmp_context.method_inst = ginst;
12450
12451         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
12452         mono_error_assert_ok (error);
12453         imethod = (MonoMethodInflated *) inflated;
12454
12455         /*FIXME but I think this is no longer necessary*/
12456         if (image_is_dynamic (method->klass->image)) {
12457                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12458                 /*
12459                  * This table maps metadata structures representing inflated methods/fields
12460                  * to the reflection objects representing their generic definitions.
12461                  */
12462                 mono_image_lock ((MonoImage*)image);
12463                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12464                 mono_image_unlock ((MonoImage*)image);
12465         }
12466
12467         if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
12468                 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
12469                 return NULL;
12470         }
12471         
12472         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
12473         return ret;
12474 }
12475
12476 MonoReflectionMethod*
12477 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12478 {
12479         MonoError error;
12480         MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
12481         mono_error_set_pending_exception (&error);
12482         return result;
12483 }
12484
12485
12486 #ifndef DISABLE_REFLECTION_EMIT
12487
12488 static MonoMethod *
12489 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12490 {
12491         MonoMethodInflated *imethod;
12492         MonoGenericContext *context;
12493         int i;
12494
12495         /*
12496          * With generic code sharing the klass might not be inflated.
12497          * This can happen because classes inflated with their own
12498          * type arguments are "normalized" to the uninflated class.
12499          */
12500         if (!klass->generic_class)
12501                 return method;
12502
12503         context = mono_class_get_context (klass);
12504
12505         if (klass->method.count && klass->methods) {
12506                 /* Find the already created inflated method */
12507                 for (i = 0; i < klass->method.count; ++i) {
12508                         g_assert (klass->methods [i]->is_inflated);
12509                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12510                                 break;
12511                 }
12512                 g_assert (i < klass->method.count);
12513                 imethod = (MonoMethodInflated*)klass->methods [i];
12514         } else {
12515                 MonoError error;
12516                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12517                 mono_error_assert_ok (&error);
12518         }
12519
12520         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12521                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12522
12523                 mono_image_lock ((MonoImage*)image);
12524                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12525                 mono_image_unlock ((MonoImage*)image);
12526         }
12527         return (MonoMethod *) imethod;
12528 }
12529
12530 static MonoMethod *
12531 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12532 {
12533         MonoMethod *method;
12534         MonoClass *gklass;
12535
12536         mono_error_init (error);
12537
12538         MonoClass *type_class = mono_object_class (type);
12539
12540         if (is_sre_generic_instance (type_class)) {
12541                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12542                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12543                 return_val_if_nok (error, NULL);
12544                 gklass = mono_class_from_mono_type (generic_type);
12545         } else if (is_sre_type_builder (type_class)) {
12546                 MonoType *t = mono_reflection_type_get_handle (type, error);
12547                 return_val_if_nok (error, NULL);
12548                 gklass = mono_class_from_mono_type (t);
12549         } else if (type->type) {
12550                 gklass = mono_class_from_mono_type (type->type);
12551                 gklass = mono_class_get_generic_type_definition (gklass);
12552         } else {
12553                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12554         }
12555
12556         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12557                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12558                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12559                 else {
12560                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12561                         if (!method)
12562                                 return NULL;
12563                 }
12564         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12565                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12566                 if (!method)
12567                         return NULL;
12568         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12569                 method = ((MonoReflectionMethod *) obj)->method;
12570         else {
12571                 method = NULL; /* prevent compiler warning */
12572                 g_error ("can't handle type %s", obj->vtable->klass->name);
12573         }
12574
12575         MonoType *t = mono_reflection_type_get_handle (type, error);
12576         return_val_if_nok (error, NULL);
12577         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12578 }
12579
12580 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12581 static gboolean
12582 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12583 {
12584         MonoGenericClass *gclass;
12585         MonoDynamicGenericClass *dgclass;
12586         MonoClass *klass, *gklass;
12587         MonoType *gtype;
12588         int i;
12589
12590         mono_error_init (error);
12591
12592         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12593         return_val_if_nok (error, FALSE);
12594         klass = mono_class_from_mono_type (gtype);
12595         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12596         gclass = gtype->data.generic_class;
12597
12598         if (!gclass->is_dynamic)
12599                 return TRUE;
12600
12601         dgclass = (MonoDynamicGenericClass *) gclass;
12602
12603         if (dgclass->initialized)
12604                 return TRUE;
12605
12606         gklass = gclass->container_class;
12607         mono_class_init (gklass);
12608
12609         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12610
12611         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12612         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12613         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12614
12615         for (i = 0; i < dgclass->count_fields; i++) {
12616                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12617                 MonoClassField *field, *inflated_field = NULL;
12618
12619                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12620                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12621                         return_val_if_nok (error, FALSE);
12622                 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12623                         field = ((MonoReflectionField *) obj)->field;
12624                 else {
12625                         field = NULL; /* prevent compiler warning */
12626                         g_assert_not_reached ();
12627                 }
12628
12629                 dgclass->fields [i] = *field;
12630                 dgclass->fields [i].parent = klass;
12631                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12632                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12633                 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12634                 dgclass->field_generic_types [i] = field->type;
12635                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12636                 dgclass->field_objects [i] = obj;
12637
12638                 if (inflated_field) {
12639                         g_free (inflated_field);
12640                 } else {
12641                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12642                 }
12643         }
12644
12645         dgclass->initialized = TRUE;
12646         return TRUE;
12647 }
12648
12649 void
12650 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12651 {
12652         MonoError error;
12653         (void) reflection_generic_class_initialize (type, fields, &error);
12654         mono_error_set_pending_exception (&error);
12655 }
12656
12657 void
12658 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12659 {
12660         MonoDynamicGenericClass *dgclass;
12661         int i;
12662
12663         g_assert (gclass->is_dynamic);
12664
12665         dgclass = (MonoDynamicGenericClass *)gclass;
12666
12667         for (i = 0; i < dgclass->count_fields; ++i) {
12668                 MonoClassField *field = dgclass->fields + i;
12669                 mono_metadata_free_type (field->type);
12670                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12671         }
12672 }
12673
12674 /**
12675  * fix_partial_generic_class:
12676  * @klass: a generic instantiation MonoClass
12677  * @error: set on error
12678  *
12679  * Assumes that the generic container of @klass has its vtable
12680  * initialized, and updates the parent class, insterfaces, methods and
12681  * fields of @klass by inflating the types using the generic context.
12682  *
12683  * On success returns TRUE, on failure returns FALSE and sets @error.
12684  *
12685  */
12686 static gboolean
12687 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12688 {
12689         MonoClass *gklass = klass->generic_class->container_class;
12690         MonoDynamicGenericClass *dgclass;
12691         int i;
12692
12693         mono_error_init (error);
12694
12695         if (klass->wastypebuilder)
12696                 return TRUE;
12697
12698         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12699         if (klass->parent != gklass->parent) {
12700                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12701                 if (mono_error_ok (error)) {
12702                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12703                         mono_metadata_free_type (parent_type);
12704                         if (parent != klass->parent) {
12705                                 /*fool mono_class_setup_parent*/
12706                                 klass->supertypes = NULL;
12707                                 mono_class_setup_parent (klass, parent);
12708                         }
12709                 } else {
12710                         if (gklass->wastypebuilder)
12711                                 klass->wastypebuilder = TRUE;
12712                         return FALSE;
12713                 }
12714         }
12715
12716         if (!dgclass->initialized)
12717                 return TRUE;
12718
12719         if (klass->method.count != gklass->method.count) {
12720                 klass->method.count = gklass->method.count;
12721                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12722
12723                 for (i = 0; i < klass->method.count; i++) {
12724                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12725                                 gklass->methods [i], klass, mono_class_get_context (klass), error);
12726                         mono_error_assert_ok (error);
12727                 }
12728         }
12729
12730         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12731                 klass->interface_count = gklass->interface_count;
12732                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12733                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12734
12735                 for (i = 0; i < gklass->interface_count; ++i) {
12736                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12737                         return_val_if_nok (error, FALSE);
12738
12739                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12740                         mono_metadata_free_type (iface_type);
12741
12742                         if (!ensure_runtime_vtable (klass->interfaces [i], error))
12743                                 return FALSE;
12744                 }
12745                 klass->interfaces_inited = 1;
12746         }
12747
12748         if (klass->field.count != gklass->field.count) {
12749                 klass->field.count = gklass->field.count;
12750                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12751
12752                 for (i = 0; i < klass->field.count; i++) {
12753                         klass->fields [i] = gklass->fields [i];
12754                         klass->fields [i].parent = klass;
12755                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12756                         return_val_if_nok (error, FALSE);
12757                 }
12758         }
12759
12760         /*We can only finish with this klass once it's parent has as well*/
12761         if (gklass->wastypebuilder)
12762                 klass->wastypebuilder = TRUE;
12763         return TRUE;
12764 }
12765
12766 /**
12767  * ensure_generic_class_runtime_vtable:
12768  * @klass a generic class
12769  * @error set on error
12770  *
12771  * Ensures that the generic container of @klass has a vtable and
12772  * returns TRUE on success.  On error returns FALSE and sets @error.
12773  */
12774 static gboolean
12775 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12776 {
12777         MonoClass *gklass = klass->generic_class->container_class;
12778
12779         mono_error_init (error);
12780
12781         if (!ensure_runtime_vtable (gklass, error))
12782                 return FALSE;
12783
12784         return fix_partial_generic_class (klass, error);
12785 }
12786
12787 /**
12788  * ensure_runtime_vtable:
12789  * @klass the class
12790  * @error set on error
12791  *
12792  * Ensures that @klass has a vtable and returns TRUE on success. On
12793  * error returns FALSE and sets @error.
12794  */
12795 static gboolean
12796 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12797 {
12798         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12799         int i, num, j;
12800
12801         mono_error_init (error);
12802
12803         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12804                 return TRUE;
12805         if (klass->parent)
12806                 if (!ensure_runtime_vtable (klass->parent, error))
12807                         return FALSE;
12808
12809         if (tb) {
12810                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12811                 num += tb->num_methods;
12812                 klass->method.count = num;
12813                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12814                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12815                 for (i = 0; i < num; ++i) {
12816                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12817                         if (!ctor)
12818                                 return FALSE;
12819                         klass->methods [i] = ctor;
12820                 }
12821                 num = tb->num_methods;
12822                 j = i;
12823                 for (i = 0; i < num; ++i) {
12824                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12825                         if (!meth)
12826                                 return FALSE;
12827                         klass->methods [j++] = meth;
12828                 }
12829         
12830                 if (tb->interfaces) {
12831                         klass->interface_count = mono_array_length (tb->interfaces);
12832                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12833                         for (i = 0; i < klass->interface_count; ++i) {
12834                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12835                                 return_val_if_nok (error, FALSE);
12836                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12837                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12838                                         return FALSE;
12839                         }
12840                         klass->interfaces_inited = 1;
12841                 }
12842         } else if (klass->generic_class){
12843                 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12844                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12845                         return FALSE;
12846                 }
12847         }
12848
12849         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12850                 int slot_num = 0;
12851                 for (i = 0; i < klass->method.count; ++i) {
12852                         MonoMethod *im = klass->methods [i];
12853                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12854                                 im->slot = slot_num++;
12855                 }
12856                 
12857                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12858                 mono_class_setup_interface_offsets (klass);
12859                 mono_class_setup_interface_id (klass);
12860         }
12861
12862         /*
12863          * The generic vtable is needed even if image->run is not set since some
12864          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12865          * method->slot being defined.
12866          */
12867
12868         /* 
12869          * tb->methods could not be freed since it is used for determining 
12870          * overrides during dynamic vtable construction.
12871          */
12872
12873         return TRUE;
12874 }
12875
12876 static MonoMethod*
12877 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12878 {
12879         mono_error_init (error);
12880         MonoClass *klass = mono_object_class (method);
12881         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12882                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12883                 return sr_method->method;
12884         }
12885         if (is_sre_method_builder (klass)) {
12886                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12887                 return mb->mhandle;
12888         }
12889         if (is_sre_method_on_tb_inst (klass)) {
12890                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12891                 MonoMethod *result;
12892                 /*FIXME move this to a proper method and unify with resolve_object*/
12893                 if (m->method_args) {
12894                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12895                 } else {
12896                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12897                         return_val_if_nok (error, NULL);
12898                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12899                         MonoMethod *mono_method;
12900
12901                         if (is_sre_method_builder (mono_object_class (m->mb)))
12902                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12903                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12904                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12905                         else
12906                                 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)));
12907
12908                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12909                 }
12910                 return result;
12911         }
12912
12913         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12914         return NULL;
12915 }
12916
12917 void
12918 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12919 {
12920         MonoReflectionTypeBuilder *tb;
12921         int i, j, onum;
12922         MonoReflectionMethod *m;
12923
12924         mono_error_init (error);
12925         *overrides = NULL;
12926         *num_overrides = 0;
12927
12928         g_assert (image_is_dynamic (klass->image));
12929
12930         if (!mono_class_get_ref_info (klass))
12931                 return;
12932
12933         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12934
12935         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12936
12937         onum = 0;
12938         if (tb->methods) {
12939                 for (i = 0; i < tb->num_methods; ++i) {
12940                         MonoReflectionMethodBuilder *mb = 
12941                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12942                         if (mb->override_methods)
12943                                 onum += mono_array_length (mb->override_methods);
12944                 }
12945         }
12946
12947         if (onum) {
12948                 *overrides = g_new0 (MonoMethod*, onum * 2);
12949
12950                 onum = 0;
12951                 for (i = 0; i < tb->num_methods; ++i) {
12952                         MonoReflectionMethodBuilder *mb = 
12953                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12954                         if (mb->override_methods) {
12955                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12956                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12957
12958                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12959                                         return_if_nok (error);
12960                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12961
12962                                         g_assert (mb->mhandle);
12963
12964                                         onum ++;
12965                                 }
12966                         }
12967                 }
12968         }
12969
12970         *num_overrides = onum;
12971 }
12972
12973 static void
12974 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12975 {
12976         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12977         MonoReflectionFieldBuilder *fb;
12978         MonoClassField *field;
12979         MonoImage *image = klass->image;
12980         const char *p, *p2;
12981         int i;
12982         guint32 len, idx, real_size = 0;
12983
12984         klass->field.count = tb->num_fields;
12985         klass->field.first = 0;
12986
12987         mono_error_init (error);
12988
12989         if (tb->class_size) {
12990                 if ((tb->packing_size & 0xffffff00) != 0) {
12991                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12992                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12993                         return;
12994                 }
12995                 klass->packing_size = tb->packing_size;
12996                 real_size = klass->instance_size + tb->class_size;
12997         }
12998
12999         if (!klass->field.count) {
13000                 klass->instance_size = MAX (klass->instance_size, real_size);
13001                 return;
13002         }
13003         
13004         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
13005         mono_class_alloc_ext (klass);
13006         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
13007         /*
13008         This is, guess what, a hack.
13009         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
13010         On the static path no field class is resolved, only types are built. This is the right thing to do
13011         but we suck.
13012         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
13013         */
13014         klass->size_inited = 1;
13015
13016         for (i = 0; i < klass->field.count; ++i) {
13017                 MonoArray *rva_data;
13018                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13019                 field = &klass->fields [i];
13020                 field->name = mono_string_to_utf8_image (image, fb->name, error);
13021                 if (!mono_error_ok (error))
13022                         return;
13023                 if (fb->attrs) {
13024                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
13025                         return_if_nok (error);
13026                         field->type = mono_metadata_type_dup (klass->image, type);
13027                         field->type->attrs = fb->attrs;
13028                 } else {
13029                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
13030                         return_if_nok (error);
13031                 }
13032
13033                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
13034                         char *base = mono_array_addr (rva_data, char, 0);
13035                         size_t size = mono_array_length (rva_data);
13036                         char *data = (char *)mono_image_alloc (klass->image, size);
13037                         memcpy (data, base, size);
13038                         klass->ext->field_def_values [i].data = data;
13039                 }
13040                 if (fb->offset != -1)
13041                         field->offset = fb->offset;
13042                 field->parent = klass;
13043                 fb->handle = field;
13044                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
13045
13046                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
13047                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
13048                 }
13049                 if (fb->def_value) {
13050                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13051                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
13052                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
13053                         /* Copy the data from the blob since it might get realloc-ed */
13054                         p = assembly->blob.data + idx;
13055                         len = mono_metadata_decode_blob_size (p, &p2);
13056                         len += p2 - p;
13057                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
13058                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
13059                 }
13060         }
13061
13062         klass->instance_size = MAX (klass->instance_size, real_size);
13063         mono_class_layout_fields (klass, klass->instance_size);
13064 }
13065
13066 static void
13067 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
13068 {
13069         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13070         MonoReflectionPropertyBuilder *pb;
13071         MonoImage *image = klass->image;
13072         MonoProperty *properties;
13073         int i;
13074
13075         mono_error_init (error);
13076
13077         if (!klass->ext)
13078                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13079
13080         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
13081         klass->ext->property.first = 0;
13082
13083         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
13084         klass->ext->properties = properties;
13085         for (i = 0; i < klass->ext->property.count; ++i) {
13086                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
13087                 properties [i].parent = klass;
13088                 properties [i].attrs = pb->attrs;
13089                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
13090                 if (!mono_error_ok (error))
13091                         return;
13092                 if (pb->get_method)
13093                         properties [i].get = pb->get_method->mhandle;
13094                 if (pb->set_method)
13095                         properties [i].set = pb->set_method->mhandle;
13096
13097                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
13098                 if (pb->def_value) {
13099                         guint32 len, idx;
13100                         const char *p, *p2;
13101                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13102                         if (!klass->ext->prop_def_values)
13103                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
13104                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
13105                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
13106                         /* Copy the data from the blob since it might get realloc-ed */
13107                         p = assembly->blob.data + idx;
13108                         len = mono_metadata_decode_blob_size (p, &p2);
13109                         len += p2 - p;
13110                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
13111                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
13112                 }
13113         }
13114 }
13115
13116 static MonoReflectionEvent *
13117 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
13118 {
13119         mono_error_init (error);
13120
13121         MonoEvent *event = g_new0 (MonoEvent, 1);
13122         MonoClass *klass;
13123
13124         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13125         if (!is_ok (error)) {
13126                 g_free (event);
13127                 return NULL;
13128         }
13129         klass = mono_class_from_mono_type (type);
13130
13131         event->parent = klass;
13132         event->attrs = eb->attrs;
13133         event->name = mono_string_to_utf8_checked (eb->name, error);
13134         if (!is_ok (error)) {
13135                 g_free (event);
13136                 return NULL;
13137         }
13138         if (eb->add_method)
13139                 event->add = eb->add_method->mhandle;
13140         if (eb->remove_method)
13141                 event->remove = eb->remove_method->mhandle;
13142         if (eb->raise_method)
13143                 event->raise = eb->raise_method->mhandle;
13144
13145 #ifndef MONO_SMALL_CONFIG
13146         if (eb->other_methods) {
13147                 int j;
13148                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
13149                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13150                         MonoReflectionMethodBuilder *mb = 
13151                                 mono_array_get (eb->other_methods,
13152                                                 MonoReflectionMethodBuilder*, j);
13153                         event->other [j] = mb->mhandle;
13154                 }
13155         }
13156 #endif
13157
13158         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
13159         if (!is_ok (error)) {
13160 #ifndef MONO_SMALL_CONFIG
13161                 g_free (event->other);
13162 #endif
13163                 g_free (event);
13164                 return NULL;
13165         }
13166         return ev_obj;
13167 }
13168
13169 MonoReflectionEvent *
13170 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13171 {
13172         MonoError error;
13173         MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13174         mono_error_set_pending_exception (&error);
13175         return result;
13176 }
13177
13178 static void
13179 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13180 {
13181         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13182         MonoReflectionEventBuilder *eb;
13183         MonoImage *image = klass->image;
13184         MonoEvent *events;
13185         int i;
13186
13187         mono_error_init (error);
13188
13189         if (!klass->ext)
13190                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13191
13192         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13193         klass->ext->event.first = 0;
13194
13195         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13196         klass->ext->events = events;
13197         for (i = 0; i < klass->ext->event.count; ++i) {
13198                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13199                 events [i].parent = klass;
13200                 events [i].attrs = eb->attrs;
13201                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13202                 if (!mono_error_ok (error))
13203                         return;
13204                 if (eb->add_method)
13205                         events [i].add = eb->add_method->mhandle;
13206                 if (eb->remove_method)
13207                         events [i].remove = eb->remove_method->mhandle;
13208                 if (eb->raise_method)
13209                         events [i].raise = eb->raise_method->mhandle;
13210
13211 #ifndef MONO_SMALL_CONFIG
13212                 if (eb->other_methods) {
13213                         int j;
13214                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13215                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13216                                 MonoReflectionMethodBuilder *mb = 
13217                                         mono_array_get (eb->other_methods,
13218                                                                         MonoReflectionMethodBuilder*, j);
13219                                 events [i].other [j] = mb->mhandle;
13220                         }
13221                 }
13222 #endif
13223                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13224         }
13225 }
13226
13227 struct remove_instantiations_user_data
13228 {
13229         MonoClass *klass;
13230         MonoError *error;
13231 };
13232
13233 static gboolean
13234 remove_instantiations_of_and_ensure_contents (gpointer key,
13235                                                   gpointer value,
13236                                                   gpointer user_data)
13237 {
13238         struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13239         MonoType *type = (MonoType*)key;
13240         MonoClass *klass = data->klass;
13241         gboolean already_failed = !is_ok (data->error);
13242         MonoError lerror;
13243         MonoError *error = already_failed ? &lerror : data->error;
13244
13245         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13246                 MonoClass *inst_klass = mono_class_from_mono_type (type);
13247                 //Ensure it's safe to use it.
13248                 if (!fix_partial_generic_class (inst_klass, error)) {
13249                         mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13250                         // Marked the class with failure, but since some other instantiation already failed,
13251                         // just report that one, and swallow the error from this one.
13252                         if (already_failed)
13253                                 mono_error_cleanup (error);
13254                 }
13255                 return TRUE;
13256         } else
13257                 return FALSE;
13258 }
13259
13260 static void
13261 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13262 {
13263         mono_error_init (error);
13264         int i;
13265
13266         if (!arr)
13267                 return;
13268
13269         for (i = 0; i < mono_array_length (arr); ++i) {
13270                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13271                 if (!mono_error_ok (error))
13272                         break;
13273         }
13274 }
13275
13276 MonoReflectionType*
13277 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13278 {
13279         MonoError error;
13280         MonoClass *klass;
13281         MonoDomain* domain;
13282         MonoReflectionType* res;
13283         int i, j;
13284
13285         mono_error_init (&error);
13286
13287         domain = mono_object_domain (tb);
13288         klass = mono_class_from_mono_type (tb->type.type);
13289
13290         /*
13291          * Check for user defined Type subclasses.
13292          */
13293         RESOLVE_TYPE (tb->parent, &error);
13294         if (!is_ok (&error))
13295                 goto failure_unlocked;
13296         check_array_for_usertypes (tb->interfaces, &error);
13297         if (!is_ok (&error))
13298                 goto failure_unlocked;
13299         if (tb->fields) {
13300                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13301                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13302                         if (fb) {
13303                                 RESOLVE_TYPE (fb->type, &error);
13304                                 if (!is_ok (&error))
13305                                         goto failure_unlocked;
13306                                 check_array_for_usertypes (fb->modreq, &error);
13307                                 if (!is_ok (&error))
13308                                         goto failure_unlocked;
13309                                 check_array_for_usertypes (fb->modopt, &error);
13310                                 if (!is_ok (&error))
13311                                         goto failure_unlocked;
13312                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13313                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13314                                         if (!is_ok (&error))
13315                                                 goto failure_unlocked;
13316                                 }
13317                         }
13318                 }
13319         }
13320         if (tb->methods) {
13321                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13322                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13323                         if (mb) {
13324                                 RESOLVE_TYPE (mb->rtype, &error);
13325                                 if (!is_ok (&error))
13326                                         goto failure_unlocked;
13327                                 check_array_for_usertypes (mb->return_modreq, &error);
13328                                 if (!is_ok (&error))
13329                                         goto failure_unlocked;
13330                                 check_array_for_usertypes (mb->return_modopt, &error);
13331                                 if (!is_ok (&error))
13332                                         goto failure_unlocked;
13333                                 check_array_for_usertypes (mb->parameters, &error);
13334                                 if (!is_ok (&error))
13335                                         goto failure_unlocked;
13336                                 if (mb->param_modreq)
13337                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13338                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13339                                                 if (!is_ok (&error))
13340                                                         goto failure_unlocked;
13341                                         }
13342                                 if (mb->param_modopt)
13343                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13344                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13345                                                 if (!is_ok (&error))
13346                                                         goto failure_unlocked;
13347                                         }
13348                         }
13349                 }
13350         }
13351         if (tb->ctors) {
13352                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13353                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13354                         if (mb) {
13355                                 check_array_for_usertypes (mb->parameters, &error);
13356                                 if (!is_ok (&error))
13357                                         goto failure_unlocked;
13358                                 if (mb->param_modreq)
13359                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13360                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13361                                                 if (!is_ok (&error))
13362                                                         goto failure_unlocked;
13363                                         }
13364                                 if (mb->param_modopt)
13365                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13366                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13367                                                 if (!is_ok (&error))
13368                                                         goto failure_unlocked;
13369                                         }
13370                         }
13371                 }
13372         }
13373
13374         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13375
13376         /* 
13377          * we need to lock the domain because the lock will be taken inside
13378          * So, we need to keep the locking order correct.
13379          */
13380         mono_loader_lock ();
13381         mono_domain_lock (domain);
13382         if (klass->wastypebuilder) {
13383                 mono_domain_unlock (domain);
13384                 mono_loader_unlock ();
13385
13386                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13387                 mono_error_set_pending_exception (&error);
13388
13389                 return res;
13390         }
13391         /*
13392          * Fields to set in klass:
13393          * the various flags: delegate/unicode/contextbound etc.
13394          */
13395         klass->flags = tb->attrs;
13396         klass->has_cctor = 1;
13397
13398         mono_class_setup_parent (klass, klass->parent);
13399         /* fool mono_class_setup_supertypes */
13400         klass->supertypes = NULL;
13401         mono_class_setup_supertypes (klass);
13402         mono_class_setup_mono_type (klass);
13403
13404 #if 0
13405         if (!((MonoDynamicImage*)klass->image)->run) {
13406                 if (klass->generic_container) {
13407                         /* FIXME: The code below can't handle generic classes */
13408                         klass->wastypebuilder = TRUE;
13409                         mono_loader_unlock ();
13410                         mono_domain_unlock (domain);
13411
13412                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13413                         mono_error_set_pending_exception (&error);
13414
13415                         return res;
13416                 }
13417         }
13418 #endif
13419
13420         /* enums are done right away */
13421         if (!klass->enumtype)
13422                 if (!ensure_runtime_vtable (klass, &error))
13423                         goto failure;
13424
13425         if (tb->subtypes) {
13426                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13427                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13428                         mono_class_alloc_ext (klass);
13429                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13430                         if (!is_ok (&error)) goto failure;
13431                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13432                 }
13433         }
13434
13435         klass->nested_classes_inited = TRUE;
13436
13437         /* fields and object layout */
13438         if (klass->parent) {
13439                 if (!klass->parent->size_inited)
13440                         mono_class_init (klass->parent);
13441                 klass->instance_size = klass->parent->instance_size;
13442                 klass->sizes.class_size = 0;
13443                 klass->min_align = klass->parent->min_align;
13444                 /* if the type has no fields we won't call the field_setup
13445                  * routine which sets up klass->has_references.
13446                  */
13447                 klass->has_references |= klass->parent->has_references;
13448         } else {
13449                 klass->instance_size = sizeof (MonoObject);
13450                 klass->min_align = 1;
13451         }
13452
13453         /* FIXME: handle packing_size and instance_size */
13454         typebuilder_setup_fields (klass, &error);
13455         if (!mono_error_ok (&error))
13456                 goto failure;
13457         typebuilder_setup_properties (klass, &error);
13458         if (!mono_error_ok (&error))
13459                 goto failure;
13460
13461         typebuilder_setup_events (klass, &error);
13462         if (!mono_error_ok (&error))
13463                 goto failure;
13464
13465         klass->wastypebuilder = TRUE;
13466
13467         /* 
13468          * If we are a generic TypeBuilder, there might be instantiations in the type cache
13469          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
13470          * we want to return normal System.MonoType objects, so clear these out from the cache.
13471          *
13472          * Together with this we must ensure the contents of all instances to match the created type.
13473          */
13474         if (domain->type_hash && klass->generic_container) {
13475                 struct remove_instantiations_user_data data;
13476                 data.klass = klass;
13477                 data.error = &error;
13478                 mono_error_assert_ok (&error);
13479                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13480                 if (!is_ok (&error))
13481                         goto failure;
13482         }
13483
13484         mono_domain_unlock (domain);
13485         mono_loader_unlock ();
13486
13487         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13488                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13489                 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13490                 goto failure_unlocked;
13491         }
13492
13493         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13494         if (!is_ok (&error))
13495                 goto failure_unlocked;
13496
13497         g_assert (res != (MonoReflectionType*)tb);
13498
13499         return res;
13500
13501 failure:
13502         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13503         klass->wastypebuilder = TRUE;
13504         mono_domain_unlock (domain);
13505         mono_loader_unlock ();
13506 failure_unlocked:
13507         mono_error_set_pending_exception (&error);
13508         return NULL;
13509 }
13510
13511 static gboolean
13512 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13513 {
13514         MonoGenericParamFull *param;
13515         MonoImage *image;
13516         MonoClass *pklass;
13517
13518         mono_error_init (error);
13519
13520         image = &gparam->tbuilder->module->dynamic_image->image;
13521
13522         param = mono_image_new0 (image, MonoGenericParamFull, 1);
13523
13524         param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13525         mono_error_assert_ok (error);
13526         param->param.num = gparam->index;
13527
13528         if (gparam->mbuilder) {
13529                 if (!gparam->mbuilder->generic_container) {
13530                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13531                         return_val_if_nok (error, FALSE);
13532
13533                         MonoClass *klass = mono_class_from_mono_type (tb);
13534                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13535                         gparam->mbuilder->generic_container->is_method = TRUE;
13536                         /* 
13537                          * Cannot set owner.method, since the MonoMethod is not created yet.
13538                          * Set the image field instead, so type_in_image () works.
13539                          */
13540                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
13541                         gparam->mbuilder->generic_container->owner.image = klass->image;
13542                 }
13543                 param->param.owner = gparam->mbuilder->generic_container;
13544         } else if (gparam->tbuilder) {
13545                 if (!gparam->tbuilder->generic_container) {
13546                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13547                         return_val_if_nok (error, FALSE);
13548                         MonoClass *klass = mono_class_from_mono_type (tb);
13549                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13550                         gparam->tbuilder->generic_container->owner.klass = klass;
13551                 }
13552                 param->param.owner = gparam->tbuilder->generic_container;
13553         }
13554
13555         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13556
13557         gparam->type.type = &pklass->byval_arg;
13558
13559         mono_class_set_ref_info (pklass, gparam);
13560         mono_image_append_class_to_reflection_info_set (pklass);
13561
13562         return TRUE;
13563 }
13564
13565 void
13566 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13567 {
13568         MonoError error;
13569         (void) reflection_initialize_generic_parameter (gparam, &error);
13570         mono_error_set_pending_exception (&error);
13571 }
13572
13573
13574 static MonoArray *
13575 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
13576 {
13577         MonoReflectionModuleBuilder *module = sig->module;
13578         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13579         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13580         guint32 buflen, i;
13581         MonoArray *result;
13582         SigBuffer buf;
13583
13584         mono_error_init (error);
13585
13586         check_array_for_usertypes (sig->arguments, error);
13587         return_val_if_nok (error, NULL);
13588
13589         sigbuffer_init (&buf, 32);
13590
13591         sigbuffer_add_value (&buf, 0x07);
13592         sigbuffer_add_value (&buf, na);
13593         if (assembly != NULL){
13594                 for (i = 0; i < na; ++i) {
13595                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13596                         encode_reflection_type (assembly, type, &buf, error);
13597                         if (!is_ok (error)) goto fail;
13598                 }
13599         }
13600
13601         buflen = buf.p - buf.buf;
13602         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13603         if (!is_ok (error)) goto fail;
13604         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13605         sigbuffer_free (&buf);
13606         return result;
13607 fail:
13608         sigbuffer_free (&buf);
13609         return NULL;
13610 }
13611
13612 MonoArray *
13613 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13614 {
13615         MonoError error;
13616         MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
13617         mono_error_set_pending_exception (&error);
13618         return result;
13619 }
13620
13621 static MonoArray *
13622 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
13623 {
13624         MonoDynamicImage *assembly = sig->module->dynamic_image;
13625         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13626         guint32 buflen, i;
13627         MonoArray *result;
13628         SigBuffer buf;
13629
13630         mono_error_init (error);
13631
13632         check_array_for_usertypes (sig->arguments, error);
13633         return_val_if_nok (error, NULL);
13634
13635         sigbuffer_init (&buf, 32);
13636
13637         sigbuffer_add_value (&buf, 0x06);
13638         for (i = 0; i < na; ++i) {
13639                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13640                 encode_reflection_type (assembly, type, &buf, error);
13641                 if (!is_ok (error))
13642                         goto fail;
13643         }
13644
13645         buflen = buf.p - buf.buf;
13646         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13647         if (!is_ok (error)) goto fail;
13648         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13649         sigbuffer_free (&buf);
13650
13651         return result;
13652 fail:
13653         sigbuffer_free (&buf);
13654         return NULL;
13655 }
13656
13657 MonoArray *
13658 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13659 {
13660         MonoError error;
13661         MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
13662         mono_error_set_pending_exception (&error);
13663         return result;
13664 }
13665
13666 typedef struct {
13667         MonoMethod *handle;
13668         MonoDomain *domain;
13669 } DynamicMethodReleaseData;
13670
13671 /*
13672  * The runtime automatically clean up those after finalization.
13673 */      
13674 static MonoReferenceQueue *dynamic_method_queue;
13675
13676 static void
13677 free_dynamic_method (void *dynamic_method)
13678 {
13679         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13680         MonoDomain *domain = data->domain;
13681         MonoMethod *method = data->handle;
13682         guint32 dis_link;
13683
13684         mono_domain_lock (domain);
13685         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13686         g_hash_table_remove (domain->method_to_dyn_method, method);
13687         mono_domain_unlock (domain);
13688         g_assert (dis_link);
13689         mono_gchandle_free (dis_link);
13690
13691         mono_runtime_free_method (domain, method);
13692         g_free (data);
13693 }
13694
13695 static gboolean
13696 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13697 {
13698         MonoReferenceQueue *queue;
13699         MonoMethod *handle;
13700         DynamicMethodReleaseData *release_data;
13701         ReflectionMethodBuilder rmb;
13702         MonoMethodSignature *sig;
13703         MonoClass *klass;
13704         MonoDomain *domain;
13705         GSList *l;
13706         int i;
13707
13708         mono_error_init (error);
13709
13710         if (mono_runtime_is_shutting_down ()) {
13711                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13712                 return FALSE;
13713         }
13714
13715         if (!(queue = dynamic_method_queue)) {
13716                 mono_loader_lock ();
13717                 if (!(queue = dynamic_method_queue))
13718                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13719                 mono_loader_unlock ();
13720         }
13721
13722         sig = dynamic_method_to_signature (mb, error);
13723         return_val_if_nok (error, FALSE);
13724
13725         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13726
13727         /*
13728          * Resolve references.
13729          */
13730         /* 
13731          * Every second entry in the refs array is reserved for storing handle_class,
13732          * which is needed by the ldtoken implementation in the JIT.
13733          */
13734         rmb.nrefs = mb->nrefs;
13735         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13736         for (i = 0; i < mb->nrefs; i += 2) {
13737                 MonoClass *handle_class;
13738                 gpointer ref;
13739                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13740
13741                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13742                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13743                         /*
13744                          * The referenced DynamicMethod should already be created by the managed
13745                          * code, except in the case of circular references. In that case, we store
13746                          * method in the refs array, and fix it up later when the referenced 
13747                          * DynamicMethod is created.
13748                          */
13749                         if (method->mhandle) {
13750                                 ref = method->mhandle;
13751                         } else {
13752                                 /* FIXME: GC object stored in unmanaged memory */
13753                                 ref = method;
13754
13755                                 /* FIXME: GC object stored in unmanaged memory */
13756                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13757                         }
13758                         handle_class = mono_defaults.methodhandle_class;
13759                 } else {
13760                         MonoException *ex = NULL;
13761                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13762                         if (!is_ok  (error)) {
13763                                 g_free (rmb.refs);
13764                                 return FALSE;
13765                         }
13766                         if (!ref)
13767                                 ex = mono_get_exception_type_load (NULL, NULL);
13768                         else if (mono_security_core_clr_enabled ())
13769                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13770
13771                         if (ex) {
13772                                 g_free (rmb.refs);
13773                                 mono_error_set_exception_instance (error, ex);
13774                                 return FALSE;
13775                         }
13776                 }
13777
13778                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13779                 rmb.refs [i + 1] = handle_class;
13780         }               
13781
13782         if (mb->owner) {
13783                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13784                 if (!is_ok (error)) {
13785                         g_free (rmb.refs);
13786                         return FALSE;
13787                 }
13788                 klass = mono_class_from_mono_type (owner_type);
13789         } else {
13790                 klass = mono_defaults.object_class;
13791         }
13792
13793         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
13794         g_free (rmb.refs);
13795         return_val_if_nok (error, FALSE);
13796
13797         release_data = g_new (DynamicMethodReleaseData, 1);
13798         release_data->handle = handle;
13799         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13800         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13801                 g_free (release_data);
13802
13803         /* Fix up refs entries pointing at us */
13804         for (l = mb->referenced_by; l; l = l->next) {
13805                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13806                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13807                 gpointer *data;
13808                 
13809                 g_assert (method->mhandle);
13810
13811                 data = (gpointer*)wrapper->method_data;
13812                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13813                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13814                                 data [i + 1] = mb->mhandle;
13815                 }
13816         }
13817         g_slist_free (mb->referenced_by);
13818
13819         /* ilgen is no longer needed */
13820         mb->ilgen = NULL;
13821
13822         domain = mono_domain_get ();
13823         mono_domain_lock (domain);
13824         if (!domain->method_to_dyn_method)
13825                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13826         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13827         mono_domain_unlock (domain);
13828
13829         return TRUE;
13830 }
13831
13832 void
13833 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13834 {
13835         MonoError error;
13836         (void) reflection_create_dynamic_method (mb, &error);
13837         mono_error_set_pending_exception (&error);
13838 }
13839
13840 #endif /* DISABLE_REFLECTION_EMIT */
13841
13842 /**
13843  * 
13844  * mono_reflection_is_valid_dynamic_token:
13845  * 
13846  * Returns TRUE if token is valid.
13847  * 
13848  */
13849 gboolean
13850 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13851 {
13852         return lookup_dyn_token (image, token) != NULL;
13853 }
13854
13855 MonoMethodSignature *
13856 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13857 {
13858         MonoMethodSignature *sig;
13859         g_assert (image_is_dynamic (image));
13860
13861         mono_error_init (error);
13862
13863         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13864         if (sig)
13865                 return sig;
13866
13867         return mono_method_signature_checked (method, error);
13868 }
13869
13870 #ifndef DISABLE_REFLECTION_EMIT
13871
13872 /**
13873  * mono_reflection_lookup_dynamic_token:
13874  *
13875  * Finish the Builder object pointed to by TOKEN and return the corresponding
13876  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13877  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13878  * mapping table.
13879  *
13880  * LOCKING: Take the loader lock
13881  */
13882 gpointer
13883 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13884 {
13885         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13886         MonoObject *obj;
13887         MonoClass *klass;
13888
13889         mono_error_init (error);
13890         
13891         obj = lookup_dyn_token (assembly, token);
13892         if (!obj) {
13893                 if (valid_token)
13894                         g_error ("Could not find required dynamic token 0x%08x", token);
13895                 else {
13896                         mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13897                         return NULL;
13898                 }
13899         }
13900
13901         if (!handle_class)
13902                 handle_class = &klass;
13903         gpointer result = resolve_object (image, obj, handle_class, context, error);
13904         return result;
13905 }
13906
13907 /*
13908  * ensure_complete_type:
13909  *
13910  *   Ensure that KLASS is completed if it is a dynamic type, or references
13911  * dynamic types.
13912  */
13913 static void
13914 ensure_complete_type (MonoClass *klass, MonoError *error)
13915 {
13916         mono_error_init (error);
13917
13918         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13919                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13920
13921                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13922                 return_if_nok (error);
13923
13924                 // Asserting here could break a lot of code
13925                 //g_assert (klass->wastypebuilder);
13926         }
13927
13928         if (klass->generic_class) {
13929                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13930                 int i;
13931
13932                 for (i = 0; i < inst->type_argc; ++i) {
13933                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13934                         return_if_nok (error);
13935                 }
13936         }
13937 }
13938
13939 static gpointer
13940 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13941 {
13942         gpointer result = NULL;
13943
13944         mono_error_init (error);
13945
13946         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13947                 result = mono_string_intern_checked ((MonoString*)obj, error);
13948                 return_val_if_nok (error, NULL);
13949                 *handle_class = mono_defaults.string_class;
13950                 g_assert (result);
13951         } else if (strcmp (obj->vtable->klass->name, "RuntimeType") == 0) {
13952                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13953                 return_val_if_nok (error, NULL);
13954                 MonoClass *mc = mono_class_from_mono_type (type);
13955                 if (!mono_class_init (mc)) {
13956                         mono_error_set_for_class_failure (error, mc);
13957                         return NULL;
13958                 }
13959
13960                 if (context) {
13961                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13962                         return_val_if_nok (error, NULL);
13963
13964                         result = mono_class_from_mono_type (inflated);
13965                         mono_metadata_free_type (inflated);
13966                 } else {
13967                         result = mono_class_from_mono_type (type);
13968                 }
13969                 *handle_class = mono_defaults.typehandle_class;
13970                 g_assert (result);
13971         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13972                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13973                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13974                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13975                 result = ((MonoReflectionMethod*)obj)->method;
13976                 if (context) {
13977                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13978                         mono_error_assert_ok (error);
13979                 }
13980                 *handle_class = mono_defaults.methodhandle_class;
13981                 g_assert (result);
13982         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13983                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13984                 result = mb->mhandle;
13985                 if (!result) {
13986                         /* Type is not yet created */
13987                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13988
13989                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13990                         return_val_if_nok (error, NULL);
13991
13992                         /*
13993                          * Hopefully this has been filled in by calling CreateType() on the
13994                          * TypeBuilder.
13995                          */
13996                         /*
13997                          * TODO: This won't work if the application finishes another 
13998                          * TypeBuilder instance instead of this one.
13999                          */
14000                         result = mb->mhandle;
14001                 }
14002                 if (context) {
14003                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14004                         mono_error_assert_ok (error);
14005                 }
14006                 *handle_class = mono_defaults.methodhandle_class;
14007         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
14008                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
14009
14010                 result = cb->mhandle;
14011                 if (!result) {
14012                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
14013
14014                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14015                         return_val_if_nok (error, NULL);
14016                         result = cb->mhandle;
14017                 }
14018                 if (context) {
14019                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14020                         mono_error_assert_ok (error);
14021                 }
14022                 *handle_class = mono_defaults.methodhandle_class;
14023         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
14024                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
14025
14026                 ensure_complete_type (field->parent, error);
14027                 return_val_if_nok (error, NULL);
14028
14029                 if (context) {
14030                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
14031                         return_val_if_nok (error, NULL);
14032
14033                         MonoClass *klass = mono_class_from_mono_type (inflated);
14034                         MonoClassField *inflated_field;
14035                         gpointer iter = NULL;
14036                         mono_metadata_free_type (inflated);
14037                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
14038                                 if (!strcmp (field->name, inflated_field->name))
14039                                         break;
14040                         }
14041                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
14042                         result = inflated_field;
14043                 } else {
14044                         result = field;
14045                 }
14046                 *handle_class = mono_defaults.fieldhandle_class;
14047                 g_assert (result);
14048         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
14049                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
14050                 result = fb->handle;
14051
14052                 if (!result) {
14053                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
14054
14055                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14056                         return_val_if_nok (error, NULL);
14057                         result = fb->handle;
14058                 }
14059
14060                 if (fb->handle && fb->handle->parent->generic_container) {
14061                         MonoClass *klass = fb->handle->parent;
14062                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
14063                         return_val_if_nok (error, NULL);
14064
14065                         MonoClass *inflated = mono_class_from_mono_type (type);
14066
14067                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
14068                         g_assert (result);
14069                         mono_metadata_free_type (type);
14070                 }
14071                 *handle_class = mono_defaults.fieldhandle_class;
14072         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
14073                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
14074                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
14075                 return_val_if_nok (error, NULL);
14076                 MonoClass *klass;
14077
14078                 klass = type->data.klass;
14079                 if (klass->wastypebuilder) {
14080                         /* Already created */
14081                         result = klass;
14082                 }
14083                 else {
14084                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14085                         return_val_if_nok (error, NULL);
14086                         result = type->data.klass;
14087                         g_assert (result);
14088                 }
14089                 *handle_class = mono_defaults.typehandle_class;
14090         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
14091                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
14092                 MonoMethodSignature *sig;
14093                 int nargs, i;
14094
14095                 if (helper->arguments)
14096                         nargs = mono_array_length (helper->arguments);
14097                 else
14098                         nargs = 0;
14099
14100                 sig = mono_metadata_signature_alloc (image, nargs);
14101                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
14102                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
14103
14104                 if (helper->unmanaged_call_conv) { /* unmanaged */
14105                         sig->call_convention = helper->unmanaged_call_conv - 1;
14106                         sig->pinvoke = TRUE;
14107                 } else if (helper->call_conv & 0x02) {
14108                         sig->call_convention = MONO_CALL_VARARG;
14109                 } else {
14110                         sig->call_convention = MONO_CALL_DEFAULT;
14111                 }
14112
14113                 sig->param_count = nargs;
14114                 /* TODO: Copy type ? */
14115                 sig->ret = helper->return_type->type;
14116                 for (i = 0; i < nargs; ++i) {
14117                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
14118                         if (!is_ok (error)) {
14119                                 image_g_free (image, sig);
14120                                 return NULL;
14121                         }
14122                 }
14123
14124                 result = sig;
14125                 *handle_class = NULL;
14126         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
14127                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
14128                 /* Already created by the managed code */
14129                 g_assert (method->mhandle);
14130                 result = method->mhandle;
14131                 *handle_class = mono_defaults.methodhandle_class;
14132         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
14133                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14134                 return_val_if_nok (error, NULL);
14135                 type = mono_class_inflate_generic_type_checked (type, context, error);
14136                 return_val_if_nok (error, NULL);
14137
14138                 result = mono_class_from_mono_type (type);
14139                 *handle_class = mono_defaults.typehandle_class;
14140                 g_assert (result);
14141                 mono_metadata_free_type (type);
14142         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
14143                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14144                 return_val_if_nok (error, NULL);
14145                 type = mono_class_inflate_generic_type_checked (type, context, error);
14146                 return_val_if_nok (error, NULL);
14147
14148                 result = mono_class_from_mono_type (type);
14149                 *handle_class = mono_defaults.typehandle_class;
14150                 g_assert (result);
14151                 mono_metadata_free_type (type);
14152         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
14153                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
14154                 MonoClass *inflated;
14155                 MonoType *type;
14156                 MonoClassField *field;
14157
14158                 if (is_sre_field_builder (mono_object_class (f->fb)))
14159                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
14160                 else if (is_sr_mono_field (mono_object_class (f->fb)))
14161                         field = ((MonoReflectionField*)f->fb)->field;
14162                 else
14163                         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)));
14164
14165                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
14166                 return_val_if_nok (error, NULL);
14167                 type = mono_class_inflate_generic_type_checked (finst, context, error);
14168                 return_val_if_nok (error, NULL);
14169
14170                 inflated = mono_class_from_mono_type (type);
14171
14172                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
14173                 ensure_complete_type (field->parent, error);
14174                 if (!is_ok (error)) {
14175                         mono_metadata_free_type (type);
14176                         return NULL;
14177                 }
14178
14179                 g_assert (result);
14180                 mono_metadata_free_type (type);
14181                 *handle_class = mono_defaults.fieldhandle_class;
14182         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
14183                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14184                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14185                 return_val_if_nok (error, NULL);
14186                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14187                 return_val_if_nok (error, NULL);
14188
14189                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14190                 MonoMethod *method;
14191
14192                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14193                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14194                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14195                         method = ((MonoReflectionMethod *)c->cb)->method;
14196                 else
14197                         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)));
14198
14199                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14200                 *handle_class = mono_defaults.methodhandle_class;
14201                 mono_metadata_free_type (type);
14202         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14203                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14204                 if (m->method_args) {
14205                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14206                         return_val_if_nok (error, NULL);
14207                         if (context) {
14208                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14209                                 mono_error_assert_ok (error);
14210                         }
14211                 } else {
14212                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14213                         return_val_if_nok (error, NULL);
14214                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14215                         return_val_if_nok (error, NULL);
14216
14217                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
14218                         MonoMethod *method;
14219
14220                         if (is_sre_method_builder (mono_object_class (m->mb)))
14221                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14222                         else if (is_sr_mono_method (mono_object_class (m->mb)))
14223                                 method = ((MonoReflectionMethod *)m->mb)->method;
14224                         else
14225                                 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)));
14226
14227                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14228                         mono_metadata_free_type (type);
14229                 }
14230                 *handle_class = mono_defaults.methodhandle_class;
14231         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14232                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14233                 MonoType *mtype;
14234                 MonoClass *klass;
14235                 MonoMethod *method;
14236                 gpointer iter;
14237                 char *name;
14238
14239                 mtype = mono_reflection_type_get_handle (m->parent, error);
14240                 return_val_if_nok (error, NULL);
14241                 klass = mono_class_from_mono_type (mtype);
14242
14243                 /* Find the method */
14244
14245                 name = mono_string_to_utf8_checked (m->name, error);
14246                 return_val_if_nok (error, NULL);
14247                 iter = NULL;
14248                 while ((method = mono_class_get_methods (klass, &iter))) {
14249                         if (!strcmp (method->name, name))
14250                                 break;
14251                 }
14252                 g_free (name);
14253
14254                 // FIXME:
14255                 g_assert (method);
14256                 // FIXME: Check parameters/return value etc. match
14257
14258                 result = method;
14259                 *handle_class = mono_defaults.methodhandle_class;
14260         } else if (is_sre_array (mono_object_get_class(obj)) ||
14261                                 is_sre_byref (mono_object_get_class(obj)) ||
14262                                 is_sre_pointer (mono_object_get_class(obj))) {
14263                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14264                 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14265                 return_val_if_nok (error, NULL);
14266
14267                 if (context) {
14268                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14269                         return_val_if_nok (error, NULL);
14270
14271                         result = mono_class_from_mono_type (inflated);
14272                         mono_metadata_free_type (inflated);
14273                 } else {
14274                         result = mono_class_from_mono_type (type);
14275                 }
14276                 *handle_class = mono_defaults.typehandle_class;
14277         } else {
14278                 g_print ("%s\n", obj->vtable->klass->name);
14279                 g_assert_not_reached ();
14280         }
14281         return result;
14282 }
14283
14284 #else /* DISABLE_REFLECTION_EMIT */
14285
14286 MonoArray*
14287 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
14288 {
14289         g_assert_not_reached ();
14290         return NULL;
14291 }
14292
14293 void
14294 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14295 {
14296         g_assert_not_reached ();
14297 }
14298
14299 void
14300 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14301 {
14302         g_assert_not_reached ();
14303 }
14304
14305 gboolean
14306 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
14307 {
14308         g_assert_not_reached ();
14309         return FALSE;
14310 }
14311
14312 void
14313 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14314 {
14315         g_assert_not_reached ();
14316 }
14317
14318 void
14319 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14320 {
14321         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14322 }
14323
14324 void
14325 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14326 {
14327         g_assert_not_reached ();
14328 }
14329
14330 void
14331 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14332 {
14333         g_assert_not_reached ();
14334 }
14335
14336 MonoReflectionModule *
14337 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14338 {
14339         g_assert_not_reached ();
14340         return NULL;
14341 }
14342
14343 guint32
14344 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14345 {
14346         g_assert_not_reached ();
14347         return 0;
14348 }
14349
14350 guint32
14351 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14352 {
14353         g_assert_not_reached ();
14354         return 0;
14355 }
14356
14357 guint32
14358 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
14359                          gboolean create_open_instance, gboolean register_token, MonoError *error)
14360 {
14361         g_assert_not_reached ();
14362         return 0;
14363 }
14364
14365 void
14366 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14367 {
14368 }
14369
14370 void
14371 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14372 {
14373         g_assert_not_reached ();
14374 }
14375
14376 void
14377 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14378 {
14379         mono_error_init (error);
14380         *overrides = NULL;
14381         *num_overrides = 0;
14382 }
14383
14384 MonoReflectionEvent *
14385 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14386 {
14387         g_assert_not_reached ();
14388         return NULL;
14389 }
14390
14391 MonoReflectionType*
14392 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14393 {
14394         g_assert_not_reached ();
14395         return NULL;
14396 }
14397
14398 void
14399 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14400 {
14401         g_assert_not_reached ();
14402 }
14403
14404 MonoArray *
14405 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14406 {
14407         g_assert_not_reached ();
14408         return NULL;
14409 }
14410
14411 MonoArray *
14412 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14413 {
14414         g_assert_not_reached ();
14415         return NULL;
14416 }
14417
14418 void 
14419 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14420 {
14421 }
14422
14423 gpointer
14424 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
14425 {
14426         mono_error_init (error);
14427         return NULL;
14428 }
14429
14430 MonoType*
14431 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14432 {
14433         mono_error_init (error);
14434         if (!ref)
14435                 return NULL;
14436         return ref->type;
14437 }
14438
14439 void
14440 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14441 {
14442         g_assert_not_reached ();
14443 }
14444
14445 #endif /* DISABLE_REFLECTION_EMIT */
14446
14447 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14448 const static guint32 declsec_flags_map[] = {
14449         0x00000000,                                     /* empty */
14450         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
14451         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
14452         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
14453         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
14454         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
14455         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
14456         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
14457         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
14458         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
14459         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
14460         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
14461         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
14462         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
14463         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
14464         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
14465         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
14466         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
14467         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
14468 };
14469
14470 /*
14471  * Returns flags that includes all available security action associated to the handle.
14472  * @token: metadata token (either for a class or a method)
14473  * @image: image where resides the metadata.
14474  */
14475 static guint32
14476 mono_declsec_get_flags (MonoImage *image, guint32 token)
14477 {
14478         int index = mono_metadata_declsec_from_index (image, token);
14479         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14480         guint32 result = 0;
14481         guint32 action;
14482         int i;
14483
14484         /* HasSecurity can be present for other, not specially encoded, attributes,
14485            e.g. SuppressUnmanagedCodeSecurityAttribute */
14486         if (index < 0)
14487                 return 0;
14488
14489         for (i = index; i < t->rows; i++) {
14490                 guint32 cols [MONO_DECL_SECURITY_SIZE];
14491
14492                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14493                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14494                         break;
14495
14496                 action = cols [MONO_DECL_SECURITY_ACTION];
14497                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14498                         result |= declsec_flags_map [action];
14499                 } else {
14500                         g_assert_not_reached ();
14501                 }
14502         }
14503         return result;
14504 }
14505
14506 /*
14507  * Get the security actions (in the form of flags) associated with the specified method.
14508  *
14509  * @method: The method for which we want the declarative security flags.
14510  * Return the declarative security flags for the method (only).
14511  *
14512  * Note: To keep MonoMethod size down we do not cache the declarative security flags
14513  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
14514  */
14515 guint32
14516 mono_declsec_flags_from_method (MonoMethod *method)
14517 {
14518         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14519                 /* FIXME: No cache (for the moment) */
14520                 guint32 idx = mono_method_get_index (method);
14521                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14522                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14523                 return mono_declsec_get_flags (method->klass->image, idx);
14524         }
14525         return 0;
14526 }
14527
14528 /*
14529  * Get the security actions (in the form of flags) associated with the specified class.
14530  *
14531  * @klass: The class for which we want the declarative security flags.
14532  * Return the declarative security flags for the class.
14533  *
14534  * Note: We cache the flags inside the MonoClass structure as this will get 
14535  *       called very often (at least for each method).
14536  */
14537 guint32
14538 mono_declsec_flags_from_class (MonoClass *klass)
14539 {
14540         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14541                 if (!klass->ext || !klass->ext->declsec_flags) {
14542                         guint32 idx;
14543
14544                         idx = mono_metadata_token_index (klass->type_token);
14545                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14546                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14547                         mono_loader_lock ();
14548                         mono_class_alloc_ext (klass);
14549                         mono_loader_unlock ();
14550                         /* we cache the flags on classes */
14551                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14552                 }
14553                 return klass->ext->declsec_flags;
14554         }
14555         return 0;
14556 }
14557
14558 /*
14559  * Get the security actions (in the form of flags) associated with the specified assembly.
14560  *
14561  * @assembly: The assembly for which we want the declarative security flags.
14562  * Return the declarative security flags for the assembly.
14563  */
14564 guint32
14565 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14566 {
14567         guint32 idx = 1; /* there is only one assembly */
14568         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14569         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14570         return mono_declsec_get_flags (assembly->image, idx);
14571 }
14572
14573
14574 /*
14575  * Fill actions for the specific index (which may either be an encoded class token or
14576  * an encoded method token) from the metadata image.
14577  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14578  */
14579 static MonoBoolean
14580 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14581         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14582 {
14583         MonoBoolean result = FALSE;
14584         MonoTableInfo *t;
14585         guint32 cols [MONO_DECL_SECURITY_SIZE];
14586         int index = mono_metadata_declsec_from_index (image, token);
14587         int i;
14588
14589         t  = &image->tables [MONO_TABLE_DECLSECURITY];
14590         for (i = index; i < t->rows; i++) {
14591                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14592
14593                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14594                         return result;
14595
14596                 /* if present only replace (class) permissions with method permissions */
14597                 /* if empty accept either class or method permissions */
14598                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14599                         if (!actions->demand.blob) {
14600                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14601                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14602                                 actions->demand.blob = (char*) (blob + 2);
14603                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14604                                 result = TRUE;
14605                         }
14606                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14607                         if (!actions->noncasdemand.blob) {
14608                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14609                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14610                                 actions->noncasdemand.blob = (char*) (blob + 2);
14611                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14612                                 result = TRUE;
14613                         }
14614                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14615                         if (!actions->demandchoice.blob) {
14616                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14617                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14618                                 actions->demandchoice.blob = (char*) (blob + 2);
14619                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14620                                 result = TRUE;
14621                         }
14622                 }
14623         }
14624
14625         return result;
14626 }
14627
14628 static MonoBoolean
14629 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14630         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14631 {
14632         guint32 idx = mono_metadata_token_index (klass->type_token);
14633         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14634         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14635         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14636 }
14637
14638 static MonoBoolean
14639 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14640         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14641 {
14642         guint32 idx = mono_method_get_index (method);
14643         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14644         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14645         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14646 }
14647
14648 /*
14649  * Collect all actions (that requires to generate code in mini) assigned for
14650  * the specified method.
14651  * Note: Don't use the content of actions if the function return FALSE.
14652  */
14653 MonoBoolean
14654 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14655 {
14656         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14657                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14658         MonoBoolean result = FALSE;
14659         guint32 flags;
14660
14661         /* quick exit if no declarative security is present in the metadata */
14662         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14663                 return FALSE;
14664
14665         /* we want the original as the wrapper is "free" of the security informations */
14666         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14667                 method = mono_marshal_method_from_wrapper (method);
14668                 if (!method)
14669                         return FALSE;
14670         }
14671
14672         /* First we look for method-level attributes */
14673         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14674                 mono_class_init (method->klass);
14675                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14676
14677                 result = mono_declsec_get_method_demands_params (method, demands, 
14678                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14679         }
14680
14681         /* Here we use (or create) the class declarative cache to look for demands */
14682         flags = mono_declsec_flags_from_class (method->klass);
14683         if (flags & mask) {
14684                 if (!result) {
14685                         mono_class_init (method->klass);
14686                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14687                 }
14688                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14689                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14690         }
14691
14692         /* The boolean return value is used as a shortcut in case nothing needs to
14693            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14694         return result;
14695 }
14696
14697
14698 /*
14699  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14700  *
14701  * Note: Don't use the content of actions if the function return FALSE.
14702  */
14703 MonoBoolean
14704 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14705 {
14706         MonoBoolean result = FALSE;
14707         guint32 flags;
14708
14709         /* quick exit if no declarative security is present in the metadata */
14710         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14711                 return FALSE;
14712
14713         /* we want the original as the wrapper is "free" of the security informations */
14714         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14715                 method = mono_marshal_method_from_wrapper (method);
14716                 if (!method)
14717                         return FALSE;
14718         }
14719
14720         /* results are independant - zeroize both */
14721         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14722         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14723
14724         /* First we look for method-level attributes */
14725         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14726                 mono_class_init (method->klass);
14727
14728                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14729                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14730         }
14731
14732         /* Here we use (or create) the class declarative cache to look for demands */
14733         flags = mono_declsec_flags_from_class (method->klass);
14734         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14735                 mono_class_init (method->klass);
14736
14737                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14738                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14739         }
14740
14741         return result;
14742 }
14743
14744 /*
14745  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14746  *
14747  * @klass       The inherited class - this is the class that provides the security check (attributes)
14748  * @demans      
14749  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14750  * 
14751  * Note: Don't use the content of actions if the function return FALSE.
14752  */
14753 MonoBoolean
14754 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14755 {
14756         MonoBoolean result = FALSE;
14757         guint32 flags;
14758
14759         /* quick exit if no declarative security is present in the metadata */
14760         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14761                 return FALSE;
14762
14763         /* Here we use (or create) the class declarative cache to look for demands */
14764         flags = mono_declsec_flags_from_class (klass);
14765         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14766                 mono_class_init (klass);
14767                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14768
14769                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14770                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14771         }
14772
14773         return result;
14774 }
14775
14776 /*
14777  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14778  *
14779  * Note: Don't use the content of actions if the function return FALSE.
14780  */
14781 MonoBoolean
14782 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14783 {
14784         /* quick exit if no declarative security is present in the metadata */
14785         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14786                 return FALSE;
14787
14788         /* we want the original as the wrapper is "free" of the security informations */
14789         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14790                 method = mono_marshal_method_from_wrapper (method);
14791                 if (!method)
14792                         return FALSE;
14793         }
14794
14795         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14796                 mono_class_init (method->klass);
14797                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14798
14799                 return mono_declsec_get_method_demands_params (method, demands, 
14800                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14801         }
14802         return FALSE;
14803 }
14804
14805
14806 static MonoBoolean
14807 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14808 {
14809         guint32 cols [MONO_DECL_SECURITY_SIZE];
14810         MonoTableInfo *t;
14811         int i;
14812
14813         int index = mono_metadata_declsec_from_index (image, token);
14814         if (index == -1)
14815                 return FALSE;
14816
14817         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14818         for (i = index; i < t->rows; i++) {
14819                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14820
14821                 /* shortcut - index are ordered */
14822                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14823                         return FALSE;
14824
14825                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14826                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14827                         entry->blob = (char*) (metadata + 2);
14828                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14829                         return TRUE;
14830                 }
14831         }
14832
14833         return FALSE;
14834 }
14835
14836 MonoBoolean
14837 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14838 {
14839         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14840                 guint32 idx = mono_method_get_index (method);
14841                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14842                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14843                 return get_declsec_action (method->klass->image, idx, action, entry);
14844         }
14845         return FALSE;
14846 }
14847
14848 MonoBoolean
14849 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14850 {
14851         /* use cache */
14852         guint32 flags = mono_declsec_flags_from_class (klass);
14853         if (declsec_flags_map [action] & flags) {
14854                 guint32 idx = mono_metadata_token_index (klass->type_token);
14855                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14856                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14857                 return get_declsec_action (klass->image, idx, action, entry);
14858         }
14859         return FALSE;
14860 }
14861
14862 MonoBoolean
14863 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14864 {
14865         guint32 idx = 1; /* there is only one assembly */
14866         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14867         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14868
14869         return get_declsec_action (assembly->image, idx, action, entry);
14870 }
14871
14872 gboolean
14873 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14874 {
14875         MonoObject *res, *exc;
14876         void *params [1];
14877         static MonoMethod *method = NULL;
14878
14879         mono_error_init (error);
14880
14881         if (method == NULL) {
14882                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14883                 g_assert (method);
14884         }
14885
14886         /* 
14887          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14888          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14889          */
14890         g_assert (mono_class_get_ref_info (klass));
14891         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14892
14893         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14894         return_val_if_nok (error, FALSE);
14895
14896         MonoError inner_error;
14897         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &inner_error);
14898
14899         if (exc || !is_ok (&inner_error)) {
14900                 mono_error_cleanup (&inner_error);
14901                 return FALSE;
14902         } else
14903                 return *(MonoBoolean*)mono_object_unbox (res);
14904 }
14905
14906 /**
14907  * mono_reflection_type_get_type:
14908  * @reftype: the System.Type object
14909  *
14910  * Returns the MonoType* associated with the C# System.Type object @reftype.
14911  */
14912 MonoType*
14913 mono_reflection_type_get_type (MonoReflectionType *reftype)
14914 {
14915         g_assert (reftype);
14916
14917         MonoError error;
14918         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14919         mono_error_assert_ok (&error);
14920         return result;
14921 }
14922
14923 /**
14924  * mono_reflection_assembly_get_assembly:
14925  * @refassembly: the System.Reflection.Assembly object
14926  *
14927  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14928  */
14929 MonoAssembly*
14930 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14931 {
14932         g_assert (refassembly);
14933
14934         return refassembly->assembly;
14935 }
14936