Merge pull request #3059 from lateralusX/jlorenss/win-x64-dyncall-gsharedvt-support
[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)
531 {
532         MONO_REQ_GC_UNSAFE_MODE;
533
534         MonoError error;
535         char *name = mono_string_to_utf8_checked (str, &error);
536         mono_error_raise_exception (&error); /* FIXME don't raise here */
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);
1673         values [MONO_METHOD_FLAGS] = mb->attrs;
1674         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1675         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1676         return_val_if_nok (error, FALSE);
1677         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1678         return_val_if_nok (error, FALSE);
1679
1680         table = &assembly->tables [MONO_TABLE_PARAM];
1681         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1682
1683         mono_image_add_decl_security (assembly, 
1684                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1685
1686         if (mb->pinfo) {
1687                 MonoDynamicTable *mtable;
1688                 guint32 *mvalues;
1689                 
1690                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1691                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1692                 
1693                 count = 0;
1694                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1695                         if (mono_array_get (mb->pinfo, gpointer, i))
1696                                 count++;
1697                 }
1698                 table->rows += count;
1699                 alloc_table (table, table->rows);
1700                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1701                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1702                         MonoReflectionParamBuilder *pb;
1703                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1704                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1705                                 values [MONO_PARAM_SEQUENCE] = i;
1706                                 if (pb->name != NULL) {
1707                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1708                                 } else {
1709                                         values [MONO_PARAM_NAME] = 0;
1710                                 }
1711                                 values += MONO_PARAM_SIZE;
1712                                 if (pb->marshal_info) {
1713                                         mtable->rows++;
1714                                         alloc_table (mtable, mtable->rows);
1715                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1716                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1717                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1718                                         return_val_if_nok (error, FALSE);
1719                                 }
1720                                 pb->table_idx = table->next_idx++;
1721                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1722                                         guint32 field_type = 0;
1723                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1724                                         mtable->rows ++;
1725                                         alloc_table (mtable, mtable->rows);
1726                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1727                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1728                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1729                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1730                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1731                                 }
1732                         }
1733                 }
1734         }
1735
1736         return TRUE;
1737 }
1738
1739 #ifndef DISABLE_REFLECTION_EMIT
1740 static gboolean
1741 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1742 {
1743         MONO_REQ_GC_UNSAFE_MODE;
1744
1745         mono_error_init (error);
1746         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1747
1748         rmb->ilgen = mb->ilgen;
1749         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1750         return_val_if_nok (error, FALSE);
1751         rmb->parameters = mb->parameters;
1752         rmb->generic_params = mb->generic_params;
1753         rmb->generic_container = mb->generic_container;
1754         rmb->opt_types = NULL;
1755         rmb->pinfo = mb->pinfo;
1756         rmb->attrs = mb->attrs;
1757         rmb->iattrs = mb->iattrs;
1758         rmb->call_conv = mb->call_conv;
1759         rmb->code = mb->code;
1760         rmb->type = mb->type;
1761         rmb->name = mb->name;
1762         rmb->table_idx = &mb->table_idx;
1763         rmb->init_locals = mb->init_locals;
1764         rmb->skip_visibility = FALSE;
1765         rmb->return_modreq = mb->return_modreq;
1766         rmb->return_modopt = mb->return_modopt;
1767         rmb->param_modreq = mb->param_modreq;
1768         rmb->param_modopt = mb->param_modopt;
1769         rmb->permissions = mb->permissions;
1770         rmb->mhandle = mb->mhandle;
1771         rmb->nrefs = 0;
1772         rmb->refs = NULL;
1773
1774         if (mb->dll) {
1775                 rmb->charset = mb->charset;
1776                 rmb->extra_flags = mb->extra_flags;
1777                 rmb->native_cc = mb->native_cc;
1778                 rmb->dllentry = mb->dllentry;
1779                 rmb->dll = mb->dll;
1780         }
1781
1782         return TRUE;
1783 }
1784
1785 static gboolean
1786 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1787 {
1788         MONO_REQ_GC_UNSAFE_MODE;
1789
1790         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1791
1792         mono_error_init (error);
1793
1794         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1795
1796         rmb->ilgen = mb->ilgen;
1797         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1798         return_val_if_nok (error, FALSE);
1799         rmb->parameters = mb->parameters;
1800         rmb->generic_params = NULL;
1801         rmb->generic_container = NULL;
1802         rmb->opt_types = NULL;
1803         rmb->pinfo = mb->pinfo;
1804         rmb->attrs = mb->attrs;
1805         rmb->iattrs = mb->iattrs;
1806         rmb->call_conv = mb->call_conv;
1807         rmb->code = NULL;
1808         rmb->type = mb->type;
1809         rmb->name = mono_string_new (mono_domain_get (), name);
1810         rmb->table_idx = &mb->table_idx;
1811         rmb->init_locals = mb->init_locals;
1812         rmb->skip_visibility = FALSE;
1813         rmb->return_modreq = NULL;
1814         rmb->return_modopt = NULL;
1815         rmb->param_modreq = mb->param_modreq;
1816         rmb->param_modopt = mb->param_modopt;
1817         rmb->permissions = mb->permissions;
1818         rmb->mhandle = mb->mhandle;
1819         rmb->nrefs = 0;
1820         rmb->refs = NULL;
1821
1822         return TRUE;
1823 }
1824
1825 static void
1826 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1827 {
1828         MONO_REQ_GC_UNSAFE_MODE;
1829
1830         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1831
1832         rmb->ilgen = mb->ilgen;
1833         rmb->rtype = mb->rtype;
1834         rmb->parameters = mb->parameters;
1835         rmb->generic_params = NULL;
1836         rmb->generic_container = NULL;
1837         rmb->opt_types = NULL;
1838         rmb->pinfo = NULL;
1839         rmb->attrs = mb->attrs;
1840         rmb->iattrs = 0;
1841         rmb->call_conv = mb->call_conv;
1842         rmb->code = NULL;
1843         rmb->type = (MonoObject *) mb->owner;
1844         rmb->name = mb->name;
1845         rmb->table_idx = NULL;
1846         rmb->init_locals = mb->init_locals;
1847         rmb->skip_visibility = mb->skip_visibility;
1848         rmb->return_modreq = NULL;
1849         rmb->return_modopt = NULL;
1850         rmb->param_modreq = NULL;
1851         rmb->param_modopt = NULL;
1852         rmb->permissions = NULL;
1853         rmb->mhandle = mb->mhandle;
1854         rmb->nrefs = 0;
1855         rmb->refs = NULL;
1856 }       
1857 #endif
1858
1859 static gboolean
1860 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1861 {
1862         MONO_REQ_GC_UNSAFE_MODE;
1863
1864         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1865         MonoDynamicTable *table;
1866         guint32 *values;
1867         guint32 tok;
1868         MonoReflectionMethod *m;
1869         int i;
1870
1871         mono_error_init (error);
1872
1873         if (!mb->override_methods)
1874                 return TRUE;
1875
1876         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1877                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1878
1879                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1880                 table->rows ++;
1881                 alloc_table (table, table->rows);
1882                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1883                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1884                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1885
1886                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1887                 return_val_if_nok (error, FALSE);
1888
1889                 switch (mono_metadata_token_table (tok)) {
1890                 case MONO_TABLE_MEMBERREF:
1891                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1892                         break;
1893                 case MONO_TABLE_METHOD:
1894                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1895                         break;
1896                 default:
1897                         g_assert_not_reached ();
1898                 }
1899                 values [MONO_METHODIMPL_DECLARATION] = tok;
1900         }
1901
1902         return TRUE;
1903 }
1904
1905 #ifndef DISABLE_REFLECTION_EMIT
1906 static gboolean
1907 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1908 {
1909         MONO_REQ_GC_UNSAFE_MODE;
1910
1911         MonoDynamicTable *table;
1912         guint32 *values;
1913         ReflectionMethodBuilder rmb;
1914         int i;
1915
1916         mono_error_init (error);
1917
1918         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1919             !mono_image_basic_method (&rmb, assembly, error))
1920                 return FALSE;
1921
1922         mb->table_idx = *rmb.table_idx;
1923
1924         if (mb->dll) { /* It's a P/Invoke method */
1925                 guint32 moduleref;
1926                 /* map CharSet values to on-disk values */
1927                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1928                 int extra_flags = mb->extra_flags;
1929                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1930                 table->rows ++;
1931                 alloc_table (table, table->rows);
1932                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1933                 
1934                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1935                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1936                 if (mb->dllentry)
1937                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1938                 else
1939                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1940                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1941                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1942                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1943                         table->rows ++;
1944                         alloc_table (table, table->rows);
1945                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1946                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1947                 }
1948         }
1949
1950         if (mb->generic_params) {
1951                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1952                 table->rows += mono_array_length (mb->generic_params);
1953                 alloc_table (table, table->rows);
1954                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1955                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1956
1957                         mono_image_get_generic_param_info (
1958                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1959                 }
1960         }
1961
1962         return TRUE;
1963 }
1964
1965 static gboolean
1966 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1967 {
1968         MONO_REQ_GC_UNSAFE_MODE;
1969
1970         ReflectionMethodBuilder rmb;
1971
1972         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1973                 return FALSE;
1974
1975         if (!mono_image_basic_method (&rmb, assembly, error))
1976                 return FALSE;
1977
1978         mb->table_idx = *rmb.table_idx;
1979
1980         return TRUE;
1981 }
1982 #endif
1983
1984 static char*
1985 type_get_fully_qualified_name (MonoType *type)
1986 {
1987         MONO_REQ_GC_NEUTRAL_MODE;
1988
1989         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1990 }
1991
1992 static char*
1993 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1994 {
1995         MONO_REQ_GC_UNSAFE_MODE;
1996
1997         MonoClass *klass;
1998         MonoAssembly *ta;
1999
2000         klass = mono_class_from_mono_type (type);
2001         if (!klass) 
2002                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2003         ta = klass->image->assembly;
2004         if (assembly_is_dynamic (ta) || (ta == ass)) {
2005                 if (klass->generic_class || klass->generic_container)
2006                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
2007                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2008                 else
2009                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2010         }
2011
2012         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2013 }
2014
2015 #ifndef DISABLE_REFLECTION_EMIT
2016 /*field_image is the image to which the eventual custom mods have been encoded against*/
2017 static guint32
2018 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2019 {
2020         MONO_REQ_GC_NEUTRAL_MODE;
2021
2022         SigBuffer buf;
2023         guint32 idx, i, token;
2024
2025         if (!assembly->save)
2026                 return 0;
2027
2028         sigbuffer_init (&buf, 32);
2029         
2030         sigbuffer_add_value (&buf, 0x06);
2031         /* encode custom attributes before the type */
2032         if (type->num_mods) {
2033                 for (i = 0; i < type->num_mods; ++i) {
2034                         if (field_image) {
2035                                 MonoError error;
2036                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2037                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2038
2039                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2040                         } else {
2041                                 token = type->modifiers [i].token;
2042                         }
2043
2044                         if (type->modifiers [i].required)
2045                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2046                         else
2047                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2048
2049                         sigbuffer_add_value (&buf, token);
2050                 }
2051         }
2052         encode_type (assembly, type, &buf);
2053         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2054         sigbuffer_free (&buf);
2055         return idx;
2056 }
2057 #endif
2058
2059 static guint32
2060 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2061 {
2062         MONO_REQ_GC_UNSAFE_MODE;
2063
2064         mono_error_init (error);
2065
2066         SigBuffer buf;
2067         guint32 idx;
2068         guint32 typespec = 0;
2069         MonoType *type;
2070         MonoClass *klass;
2071
2072         init_type_builder_generics (fb->type, error);
2073         return_val_if_nok (error, 0);
2074
2075         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2076         return_val_if_nok (error, 0);
2077         klass = mono_class_from_mono_type (type);
2078
2079         sigbuffer_init (&buf, 32);
2080         
2081         sigbuffer_add_value (&buf, 0x06);
2082         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2083         if (!is_ok (error))
2084                 goto fail;
2085         /* encode custom attributes before the type */
2086
2087         if (klass->generic_container)
2088                 typespec = create_typespec (assembly, type);
2089
2090         if (typespec) {
2091                 MonoGenericClass *gclass;
2092                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2093                 encode_generic_class (assembly, gclass, &buf);
2094         } else {
2095                 encode_type (assembly, type, &buf);
2096         }
2097         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2098         sigbuffer_free (&buf);
2099         return idx;
2100 fail:
2101         sigbuffer_free (&buf);
2102         return 0;
2103 }
2104
2105 static guint32
2106 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2107 {
2108         MONO_REQ_GC_UNSAFE_MODE;
2109
2110         char blob_size [64];
2111         char *b = blob_size;
2112         char *box_val;
2113         char* buf;
2114         guint32 idx = 0, len = 0, dummy = 0;
2115
2116         buf = (char *)g_malloc (64);
2117         if (!val) {
2118                 *ret_type = MONO_TYPE_CLASS;
2119                 len = 4;
2120                 box_val = (char*)&dummy;
2121         } else {
2122                 box_val = ((char*)val) + sizeof (MonoObject);
2123                 *ret_type = val->vtable->klass->byval_arg.type;
2124         }
2125 handle_enum:
2126         switch (*ret_type) {
2127         case MONO_TYPE_BOOLEAN:
2128         case MONO_TYPE_U1:
2129         case MONO_TYPE_I1:
2130                 len = 1;
2131                 break;
2132         case MONO_TYPE_CHAR:
2133         case MONO_TYPE_U2:
2134         case MONO_TYPE_I2:
2135                 len = 2;
2136                 break;
2137         case MONO_TYPE_U4:
2138         case MONO_TYPE_I4:
2139         case MONO_TYPE_R4:
2140                 len = 4;
2141                 break;
2142         case MONO_TYPE_U8:
2143         case MONO_TYPE_I8:
2144                 len = 8;
2145                 break;
2146         case MONO_TYPE_R8:
2147                 len = 8;
2148                 break;
2149         case MONO_TYPE_VALUETYPE: {
2150                 MonoClass *klass = val->vtable->klass;
2151                 
2152                 if (klass->enumtype) {
2153                         *ret_type = mono_class_enum_basetype (klass)->type;
2154                         goto handle_enum;
2155                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2156                         len = 8;
2157                 } else 
2158                         g_error ("we can't encode valuetypes, we should have never reached this line");
2159                 break;
2160         }
2161         case MONO_TYPE_CLASS:
2162                 break;
2163         case MONO_TYPE_STRING: {
2164                 MonoString *str = (MonoString*)val;
2165                 /* there is no signature */
2166                 len = str->length * 2;
2167                 mono_metadata_encode_value (len, b, &b);
2168 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2169                 {
2170                         char *swapped = g_malloc (2 * mono_string_length (str));
2171                         const char *p = (const char*)mono_string_chars (str);
2172
2173                         swap_with_size (swapped, p, 2, mono_string_length (str));
2174                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2175                         g_free (swapped);
2176                 }
2177 #else
2178                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2179 #endif
2180
2181                 g_free (buf);
2182                 return idx;
2183         }
2184         case MONO_TYPE_GENERICINST:
2185                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2186                 goto handle_enum;
2187         default:
2188                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2189         }
2190
2191         /* there is no signature */
2192         mono_metadata_encode_value (len, b, &b);
2193 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2194         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2195         swap_with_size (blob_size, box_val, len, 1);
2196         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2197 #else
2198         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2199 #endif
2200
2201         g_free (buf);
2202         return idx;
2203 }
2204
2205 static guint32
2206 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2207 {
2208         MONO_REQ_GC_UNSAFE_MODE;
2209
2210         mono_error_init (error);
2211
2212         char *str;
2213         SigBuffer buf;
2214         guint32 idx, len;
2215
2216         sigbuffer_init (&buf, 32);
2217
2218         sigbuffer_add_value (&buf, minfo->type);
2219
2220         switch (minfo->type) {
2221         case MONO_NATIVE_BYVALTSTR:
2222         case MONO_NATIVE_BYVALARRAY:
2223                 sigbuffer_add_value (&buf, minfo->count);
2224                 break;
2225         case MONO_NATIVE_LPARRAY:
2226                 if (minfo->eltype || minfo->has_size) {
2227                         sigbuffer_add_value (&buf, minfo->eltype);
2228                         if (minfo->has_size) {
2229                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2230                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2231
2232                                 /* LAMESPEC: ElemMult is undocumented */
2233                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2234                         }
2235                 }
2236                 break;
2237         case MONO_NATIVE_SAFEARRAY:
2238                 if (minfo->eltype)
2239                         sigbuffer_add_value (&buf, minfo->eltype);
2240                 break;
2241         case MONO_NATIVE_CUSTOM:
2242                 if (minfo->guid) {
2243                         str = mono_string_to_utf8_checked (minfo->guid, error);
2244                         if (!is_ok (error)) {
2245                                 sigbuffer_free (&buf);
2246                                 return 0;
2247                         }
2248                         len = strlen (str);
2249                         sigbuffer_add_value (&buf, len);
2250                         sigbuffer_add_mem (&buf, str, len);
2251                         g_free (str);
2252                 } else {
2253                         sigbuffer_add_value (&buf, 0);
2254                 }
2255                 /* native type name */
2256                 sigbuffer_add_value (&buf, 0);
2257                 /* custom marshaler type name */
2258                 if (minfo->marshaltype || minfo->marshaltyperef) {
2259                         if (minfo->marshaltyperef) {
2260                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2261                                 if (!is_ok (error)) {
2262                                         sigbuffer_free (&buf);
2263                                         return 0;
2264                                 }
2265                                 str = type_get_fully_qualified_name (marshaltype);
2266                         } else {
2267                                 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
2268                                 if (!is_ok (error)) {
2269                                         sigbuffer_free (&buf);
2270                                         return 0;
2271                                 }
2272                         }
2273                         len = strlen (str);
2274                         sigbuffer_add_value (&buf, len);
2275                         sigbuffer_add_mem (&buf, str, len);
2276                         g_free (str);
2277                 } else {
2278                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2279                         sigbuffer_add_value (&buf, 0);
2280                 }
2281                 if (minfo->mcookie) {
2282                         str = mono_string_to_utf8_checked (minfo->mcookie, error);
2283                         if (!is_ok (error)) {
2284                                 sigbuffer_free (&buf);
2285                                 return 0;
2286                         }
2287                         len = strlen (str);
2288                         sigbuffer_add_value (&buf, len);
2289                         sigbuffer_add_mem (&buf, str, len);
2290                         g_free (str);
2291                 } else {
2292                         sigbuffer_add_value (&buf, 0);
2293                 }
2294                 break;
2295         default:
2296                 break;
2297         }
2298         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2299         sigbuffer_free (&buf);
2300         return idx;
2301 }
2302
2303 static void
2304 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2305 {
2306         MONO_REQ_GC_UNSAFE_MODE;
2307
2308         mono_error_init (error);
2309
2310         MonoDynamicTable *table;
2311         guint32 *values;
2312
2313         /* maybe this fixup should be done in the C# code */
2314         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2315                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2316         table = &assembly->tables [MONO_TABLE_FIELD];
2317         fb->table_idx = table->next_idx ++;
2318         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2319         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2320         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2321         values [MONO_FIELD_FLAGS] = fb->attrs;
2322         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2323         return_if_nok (error);
2324
2325
2326         if (fb->offset != -1) {
2327                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2328                 table->rows ++;
2329                 alloc_table (table, table->rows);
2330                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2331                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2332                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2333         }
2334         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2335                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2336                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2337                 table->rows ++;
2338                 alloc_table (table, table->rows);
2339                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2340                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2341                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2342                 values [MONO_CONSTANT_TYPE] = field_type;
2343                 values [MONO_CONSTANT_PADDING] = 0;
2344         }
2345         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2346                 guint32 rva_idx;
2347                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2348                 table->rows ++;
2349                 alloc_table (table, table->rows);
2350                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2351                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2352                 /*
2353                  * We store it in the code section because it's simpler for now.
2354                  */
2355                 if (fb->rva_data) {
2356                         if (mono_array_length (fb->rva_data) >= 10)
2357                                 stream_data_align (&assembly->code);
2358                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2359                 } else
2360                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2361                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2362         }
2363         if (fb->marshal_info) {
2364                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2365                 table->rows ++;
2366                 alloc_table (table, table->rows);
2367                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2368                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2369                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2370                 return_if_nok (error);
2371         }
2372 }
2373
2374 static guint32
2375 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2376 {
2377         MONO_REQ_GC_UNSAFE_MODE;
2378
2379         mono_error_init (error);
2380
2381         SigBuffer buf;
2382         guint32 nparams = 0;
2383         MonoReflectionMethodBuilder *mb = fb->get_method;
2384         MonoReflectionMethodBuilder *smb = fb->set_method;
2385         guint32 idx, i;
2386
2387         if (mb && mb->parameters)
2388                 nparams = mono_array_length (mb->parameters);
2389         if (!mb && smb && smb->parameters)
2390                 nparams = mono_array_length (smb->parameters) - 1;
2391         sigbuffer_init (&buf, 32);
2392         if (fb->call_conv & 0x20)
2393                 sigbuffer_add_byte (&buf, 0x28);
2394         else
2395                 sigbuffer_add_byte (&buf, 0x08);
2396         sigbuffer_add_value (&buf, nparams);
2397         if (mb) {
2398                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2399                 if (!is_ok (error))
2400                         goto fail;
2401                 for (i = 0; i < nparams; ++i) {
2402                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2403                         encode_reflection_type (assembly, pt, &buf, error);
2404                         if (!is_ok (error))
2405                                 goto fail;
2406                 }
2407         } else if (smb && smb->parameters) {
2408                 /* the property type is the last param */
2409                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2410                 if (!is_ok (error))
2411                         goto fail;
2412
2413                 for (i = 0; i < nparams; ++i) {
2414                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2415                         encode_reflection_type (assembly, pt, &buf, error);
2416                         if (!is_ok (error))
2417                                 goto fail;
2418                 }
2419         } else {
2420                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2421                 if (!is_ok (error))
2422                         goto fail;
2423         }
2424
2425         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2426         sigbuffer_free (&buf);
2427         return idx;
2428 fail:
2429         sigbuffer_free (&buf);
2430         return 0;
2431 }
2432
2433 static void
2434 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2435 {
2436         MONO_REQ_GC_UNSAFE_MODE;
2437
2438         mono_error_init (error);
2439
2440         MonoDynamicTable *table;
2441         guint32 *values;
2442         guint num_methods = 0;
2443         guint32 semaidx;
2444
2445         /* 
2446          * we need to set things in the following tables:
2447          * PROPERTYMAP (info already filled in _get_type_info ())
2448          * PROPERTY    (rows already preallocated in _get_type_info ())
2449          * METHOD      (method info already done with the generic method code)
2450          * METHODSEMANTICS
2451          * CONSTANT
2452          */
2453         table = &assembly->tables [MONO_TABLE_PROPERTY];
2454         pb->table_idx = table->next_idx ++;
2455         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2456         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2457         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2458         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2459         return_if_nok (error);
2460
2461
2462         /* FIXME: we still don't handle 'other' methods */
2463         if (pb->get_method) num_methods ++;
2464         if (pb->set_method) num_methods ++;
2465
2466         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2467         table->rows += num_methods;
2468         alloc_table (table, table->rows);
2469
2470         if (pb->get_method) {
2471                 semaidx = table->next_idx ++;
2472                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2473                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2474                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2475                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2476         }
2477         if (pb->set_method) {
2478                 semaidx = table->next_idx ++;
2479                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2480                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2481                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2482                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2483         }
2484         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2485                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2486                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2487                 table->rows ++;
2488                 alloc_table (table, table->rows);
2489                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2490                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2491                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2492                 values [MONO_CONSTANT_TYPE] = field_type;
2493                 values [MONO_CONSTANT_PADDING] = 0;
2494         }
2495 }
2496
2497 static void
2498 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2499 {
2500         MONO_REQ_GC_UNSAFE_MODE;
2501
2502         MonoDynamicTable *table;
2503         guint32 *values;
2504         guint num_methods = 0;
2505         guint32 semaidx;
2506
2507         /* 
2508          * we need to set things in the following tables:
2509          * EVENTMAP (info already filled in _get_type_info ())
2510          * EVENT    (rows already preallocated in _get_type_info ())
2511          * METHOD      (method info already done with the generic method code)
2512          * METHODSEMANTICS
2513          */
2514         table = &assembly->tables [MONO_TABLE_EVENT];
2515         eb->table_idx = table->next_idx ++;
2516         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2517         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2518         values [MONO_EVENT_FLAGS] = eb->attrs;
2519         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2520         return_if_nok (error);
2521         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2522
2523         /*
2524          * FIXME: we still don't handle 'other' methods 
2525          */
2526         if (eb->add_method) num_methods ++;
2527         if (eb->remove_method) num_methods ++;
2528         if (eb->raise_method) num_methods ++;
2529
2530         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2531         table->rows += num_methods;
2532         alloc_table (table, table->rows);
2533
2534         if (eb->add_method) {
2535                 semaidx = table->next_idx ++;
2536                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2537                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2538                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2539                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2540         }
2541         if (eb->remove_method) {
2542                 semaidx = table->next_idx ++;
2543                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2544                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2545                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2546                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2547         }
2548         if (eb->raise_method) {
2549                 semaidx = table->next_idx ++;
2550                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2551                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2552                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2553                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2554         }
2555 }
2556
2557 static void
2558 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2559 {
2560         MONO_REQ_GC_UNSAFE_MODE;
2561
2562         mono_error_init (error);
2563
2564         MonoDynamicTable *table;
2565         guint32 num_constraints, i;
2566         guint32 *values;
2567         guint32 table_idx;
2568
2569         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2570         num_constraints = gparam->iface_constraints ?
2571                 mono_array_length (gparam->iface_constraints) : 0;
2572         table->rows += num_constraints;
2573         if (gparam->base_type)
2574                 table->rows++;
2575         alloc_table (table, table->rows);
2576
2577         if (gparam->base_type) {
2578                 table_idx = table->next_idx ++;
2579                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2580
2581                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2582                 return_if_nok (error);
2583                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2584                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2585         }
2586
2587         for (i = 0; i < num_constraints; i++) {
2588                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2589                         gparam->iface_constraints, gpointer, i);
2590
2591                 table_idx = table->next_idx ++;
2592                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2593
2594                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2595                 return_if_nok (error);
2596
2597                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2598                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2599         }
2600 }
2601
2602 static void
2603 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2604 {
2605         MONO_REQ_GC_UNSAFE_MODE;
2606
2607         GenericParamTableEntry *entry;
2608
2609         /*
2610          * The GenericParam table must be sorted according to the `owner' field.
2611          * We need to do this sorting prior to writing the GenericParamConstraint
2612          * table, since we have to use the final GenericParam table indices there
2613          * and they must also be sorted.
2614          */
2615
2616         entry = g_new0 (GenericParamTableEntry, 1);
2617         entry->owner = owner;
2618         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2619         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2620         entry->gparam = gparam;
2621         
2622         g_ptr_array_add (assembly->gen_params, entry);
2623 }
2624
2625 static gboolean
2626 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2627 {
2628         MONO_REQ_GC_UNSAFE_MODE;
2629
2630         MonoDynamicTable *table;
2631         MonoGenericParam *param;
2632         guint32 *values;
2633         guint32 table_idx;
2634
2635         mono_error_init (error);
2636
2637         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2638         table_idx = table->next_idx ++;
2639         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2640
2641         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2642         return_val_if_nok (error, FALSE);
2643
2644         param = gparam_type->data.generic_param;
2645
2646         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2647         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2648         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2649         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2650
2651         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2652                 return FALSE;
2653
2654         encode_constraints (entry->gparam, table_idx, assembly, error);
2655         return_val_if_nok (error, FALSE);
2656
2657         return TRUE;
2658 }
2659
2660 static guint32
2661 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2662 {
2663         MONO_REQ_GC_UNSAFE_MODE;
2664
2665         MonoDynamicTable *table;
2666         guint32 token;
2667         guint32 *values;
2668         guint32 cols [MONO_ASSEMBLY_SIZE];
2669         const char *pubkey;
2670         guint32 publen;
2671
2672         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2673                 return token;
2674
2675         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2676                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2677                 token = table->next_idx ++;
2678                 table->rows ++;
2679                 alloc_table (table, table->rows);
2680                 values = table->values + token * MONO_MODULEREF_SIZE;
2681                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2682
2683                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2684                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2685                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2686
2687                 return token;
2688         }
2689         
2690         if (assembly_is_dynamic (image->assembly))
2691                 /* FIXME: */
2692                 memset (cols, 0, sizeof (cols));
2693         else {
2694                 /* image->assembly->image is the manifest module */
2695                 image = image->assembly->image;
2696                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2697         }
2698
2699         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2700         token = table->next_idx ++;
2701         table->rows ++;
2702         alloc_table (table, table->rows);
2703         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2704         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2705         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2706         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2707         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2708         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2709         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2710         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2711         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2712
2713         if (strcmp ("", image->assembly->aname.culture)) {
2714                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2715                                 image->assembly->aname.culture);
2716         }
2717
2718         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2719                 guchar pubtoken [9];
2720                 pubtoken [0] = 8;
2721                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2722                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2723         } else {
2724                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2725         }
2726         token <<= MONO_RESOLUTION_SCOPE_BITS;
2727         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2728         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2729         return token;
2730 }
2731
2732 static guint32
2733 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2734 {
2735         MONO_REQ_GC_NEUTRAL_MODE;
2736
2737         MonoDynamicTable *table;
2738         guint32 *values;
2739         guint32 token;
2740         SigBuffer buf;
2741
2742         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2743                 return token;
2744
2745         sigbuffer_init (&buf, 32);
2746         switch (type->type) {
2747         case MONO_TYPE_FNPTR:
2748         case MONO_TYPE_PTR:
2749         case MONO_TYPE_SZARRAY:
2750         case MONO_TYPE_ARRAY:
2751         case MONO_TYPE_VAR:
2752         case MONO_TYPE_MVAR:
2753         case MONO_TYPE_GENERICINST:
2754                 encode_type (assembly, type, &buf);
2755                 break;
2756         case MONO_TYPE_CLASS:
2757         case MONO_TYPE_VALUETYPE: {
2758                 MonoClass *k = mono_class_from_mono_type (type);
2759                 if (!k || !k->generic_container) {
2760                         sigbuffer_free (&buf);
2761                         return 0;
2762                 }
2763                 encode_type (assembly, type, &buf);
2764                 break;
2765         }
2766         default:
2767                 sigbuffer_free (&buf);
2768                 return 0;
2769         }
2770
2771         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2772         if (assembly->save) {
2773                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2774                 alloc_table (table, table->rows + 1);
2775                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2776                 values [MONO_TYPESPEC_SIGNATURE] = token;
2777         }
2778         sigbuffer_free (&buf);
2779
2780         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2781         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2782         table->next_idx ++;
2783         return token;
2784 }
2785
2786 static guint32
2787 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2788 {
2789         MONO_REQ_GC_UNSAFE_MODE;
2790
2791         MonoDynamicTable *table;
2792         guint32 *values;
2793         guint32 token, scope, enclosing;
2794         MonoClass *klass;
2795
2796         /* if the type requires a typespec, we must try that first*/
2797         if (try_typespec && (token = create_typespec (assembly, type)))
2798                 return token;
2799         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2800         if (token)
2801                 return token;
2802         klass = mono_class_from_mono_type (type);
2803         if (!klass)
2804                 klass = mono_class_from_mono_type (type);
2805
2806         /*
2807          * If it's in the same module and not a generic type parameter:
2808          */
2809         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2810                         (type->type != MONO_TYPE_MVAR)) {
2811                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2812                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2813                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2814                 return token;
2815         }
2816
2817         if (klass->nested_in) {
2818                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2819                 /* get the typeref idx of the enclosing type */
2820                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2821                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2822         } else {
2823                 scope = resolution_scope_from_image (assembly, klass->image);
2824         }
2825         table = &assembly->tables [MONO_TABLE_TYPEREF];
2826         if (assembly->save) {
2827                 alloc_table (table, table->rows + 1);
2828                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2829                 values [MONO_TYPEREF_SCOPE] = scope;
2830                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2831                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2832         }
2833         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2834         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2835         table->next_idx ++;
2836         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2837         return token;
2838 }
2839
2840 /*
2841  * Despite the name, we handle also TypeSpec (with the above helper).
2842  */
2843 static guint32
2844 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2845 {
2846         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2847 }
2848
2849 #ifndef DISABLE_REFLECTION_EMIT
2850 static guint32
2851 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2852 {
2853         MONO_REQ_GC_NEUTRAL_MODE;
2854
2855         MonoDynamicTable *table;
2856         guint32 *values;
2857         guint32 token, pclass;
2858
2859         switch (parent & MONO_TYPEDEFORREF_MASK) {
2860         case MONO_TYPEDEFORREF_TYPEREF:
2861                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2862                 break;
2863         case MONO_TYPEDEFORREF_TYPESPEC:
2864                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2865                 break;
2866         case MONO_TYPEDEFORREF_TYPEDEF:
2867                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2868                 break;
2869         default:
2870                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2871                 return 0;
2872         }
2873         /* extract the index */
2874         parent >>= MONO_TYPEDEFORREF_BITS;
2875
2876         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2877
2878         if (assembly->save) {
2879                 alloc_table (table, table->rows + 1);
2880                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2881                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2882                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2883                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2884         }
2885
2886         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2887         table->next_idx ++;
2888
2889         return token;
2890 }
2891
2892 /*
2893  * Insert a memberef row into the metadata: the token that point to the memberref
2894  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2895  * mono_image_get_fieldref_token()).
2896  * The sig param is an index to an already built signature.
2897  */
2898 static guint32
2899 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2900 {
2901         MONO_REQ_GC_NEUTRAL_MODE;
2902
2903         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2904         return mono_image_add_memberef_row (assembly, parent, name, sig);
2905 }
2906
2907
2908 static guint32
2909 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2910 {
2911         MONO_REQ_GC_NEUTRAL_MODE;
2912
2913         guint32 token;
2914         MonoMethodSignature *sig;
2915         
2916         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2917
2918         if (create_typespec) {
2919                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2920                 if (token)
2921                         return token;
2922         } 
2923
2924         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2925         if (token && !create_typespec)
2926                 return token;
2927
2928         g_assert (!method->is_inflated);
2929         if (!token) {
2930                 /*
2931                  * A methodref signature can't contain an unmanaged calling convention.
2932                  */
2933                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2934                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2935                         sig->call_convention = MONO_CALL_DEFAULT;
2936                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2937                         method->name,  method_encode_signature (assembly, sig));
2938                 g_free (sig);
2939                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2940         }
2941
2942         if (create_typespec) {
2943                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2944                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2945                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2946
2947                 if (assembly->save) {
2948                         guint32 *values;
2949
2950                         alloc_table (table, table->rows + 1);
2951                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2952                         values [MONO_METHODSPEC_METHOD] = token;
2953                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2954                 }
2955
2956                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2957                 table->next_idx ++;
2958                 /*methodspec and memberef tokens are diferent, */
2959                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2960                 return token;
2961         }
2962         return token;
2963 }
2964
2965 static guint32
2966 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2967 {
2968         guint32 token, parent, sig;
2969         ReflectionMethodBuilder rmb;
2970         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2971         
2972         mono_error_init (error);
2973         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2974         if (token)
2975                 return token;
2976
2977         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2978                 return 0;
2979
2980         /*
2981          * A methodref signature can't contain an unmanaged calling convention.
2982          * Since some flags are encoded as part of call_conv, we need to check against it.
2983         */
2984         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2985                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2986
2987         sig = method_builder_encode_signature (assembly, &rmb, error);
2988         return_val_if_nok (error, 0);
2989
2990         if (tb->generic_params) {
2991                 parent = create_generic_typespec (assembly, tb, error);
2992                 return_val_if_nok (error, 0);
2993         } else {
2994                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2995                 return_val_if_nok (error, 0);
2996
2997                 parent = mono_image_typedef_or_ref (assembly, t);
2998         }
2999
3000         char *name = mono_string_to_utf8_checked (method->name, error);
3001         return_val_if_nok (error, 0);
3002
3003         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3004         g_free (name);
3005
3006         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3007
3008         return token;
3009 }
3010
3011 static guint32
3012 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
3013                                      const gchar *name, guint32 sig)
3014 {
3015         MonoDynamicTable *table;
3016         guint32 token;
3017         guint32 *values;
3018         
3019         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3020
3021         if (assembly->save) {
3022                 alloc_table (table, table->rows + 1);
3023                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3024                 values [MONO_MEMBERREF_CLASS] = original;
3025                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3026                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3027         }
3028
3029         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3030         table->next_idx ++;
3031
3032         return token;
3033 }
3034
3035 static guint32
3036 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3037 {
3038         SigBuffer buf;
3039         int i;
3040         guint32 nparams = mono_array_length (mb->generic_params);
3041         guint32 idx;
3042
3043         if (!assembly->save)
3044                 return 0;
3045
3046         sigbuffer_init (&buf, 32);
3047
3048         sigbuffer_add_value (&buf, 0xa);
3049         sigbuffer_add_value (&buf, nparams);
3050
3051         for (i = 0; i < nparams; i++) {
3052                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3053                 sigbuffer_add_value (&buf, i);
3054         }
3055
3056         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3057         sigbuffer_free (&buf);
3058         return idx;
3059 }
3060
3061 static guint32
3062 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3063 {
3064         MonoDynamicTable *table;
3065         guint32 *values;
3066         guint32 token, mtoken = 0;
3067
3068         mono_error_init (error);
3069         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3070         if (token)
3071                 return token;
3072
3073         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3074
3075         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3076         if (!mono_error_ok (error))
3077                 return 0;
3078
3079         switch (mono_metadata_token_table (mtoken)) {
3080         case MONO_TABLE_MEMBERREF:
3081                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3082                 break;
3083         case MONO_TABLE_METHOD:
3084                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3085                 break;
3086         default:
3087                 g_assert_not_reached ();
3088         }
3089
3090         if (assembly->save) {
3091                 alloc_table (table, table->rows + 1);
3092                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3093                 values [MONO_METHODSPEC_METHOD] = mtoken;
3094                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3095         }
3096
3097         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3098         table->next_idx ++;
3099
3100         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3101         return token;
3102 }
3103
3104 static guint32
3105 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3106 {
3107         guint32 token;
3108
3109         mono_error_init (error);
3110
3111         if (mb->generic_params && create_methodspec) 
3112                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3113
3114         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3115         if (token)
3116                 return token;
3117
3118         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3119         if (!mono_error_ok (error))
3120                 return 0;
3121         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3122         return token;
3123 }
3124
3125 static guint32
3126 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3127 {
3128         guint32 token, parent, sig;
3129         ReflectionMethodBuilder rmb;
3130         char *name;
3131         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3132         
3133         mono_error_init (error);
3134         
3135         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3136         if (token)
3137                 return token;
3138
3139         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3140                 return 0;
3141
3142         if (tb->generic_params) {
3143                 parent = create_generic_typespec (assembly, tb, error);
3144                 return_val_if_nok (error, 0);
3145         } else {
3146                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3147                 return_val_if_nok (error, 0);
3148                 parent = mono_image_typedef_or_ref (assembly, type);
3149         }
3150         
3151         name = mono_string_to_utf8_checked (rmb.name, error);
3152         return_val_if_nok (error, 0);
3153         sig = method_builder_encode_signature (assembly, &rmb, error);
3154         return_val_if_nok (error, 0);
3155
3156         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3157
3158         g_free (name);
3159         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3160         return token;
3161 }
3162 #endif
3163
3164 static gboolean
3165 is_field_on_inst (MonoClassField *field)
3166 {
3167         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3168 }
3169
3170 /*
3171  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3172  */
3173 static MonoType*
3174 get_field_on_inst_generic_type (MonoClassField *field)
3175 {
3176         MonoClass *klass, *gtd;
3177         MonoDynamicGenericClass *dgclass;
3178         int field_index;
3179
3180         g_assert (is_field_on_inst (field));
3181
3182         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3183
3184         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3185                 field_index = field - dgclass->fields;
3186                 return dgclass->field_generic_types [field_index];              
3187         }
3188
3189         klass = field->parent;
3190         gtd = klass->generic_class->container_class;
3191
3192         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3193                 field_index = field - klass->fields;
3194                 return gtd->fields [field_index].type;
3195         }
3196
3197         g_assert_not_reached ();
3198         return 0;
3199 }
3200
3201 #ifndef DISABLE_REFLECTION_EMIT
3202 static guint32
3203 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3204 {
3205         MonoType *type;
3206         guint32 token;
3207
3208         g_assert (field);
3209         g_assert (field->parent);
3210
3211         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3212         if (token)
3213                 return token;
3214
3215         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3216                 int index = field - field->parent->fields;
3217                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3218         } else {
3219                 if (is_field_on_inst (field))
3220                         type = get_field_on_inst_generic_type (field);
3221                 else
3222                         type = mono_field_get_type (field);
3223         }
3224         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3225                                                                                         mono_field_get_name (field),
3226                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3227         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3228         return token;
3229 }
3230
3231 static guint32
3232 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3233 {
3234         guint32 token;
3235         MonoClass *klass;
3236         MonoGenericClass *gclass;
3237         MonoType *type;
3238         char *name;
3239
3240         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3241         if (token)
3242                 return token;
3243         if (is_sre_field_builder (mono_object_class (f->fb))) {
3244                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3245                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3246                 return_val_if_nok (error, 0);
3247                 klass = mono_class_from_mono_type (type);
3248                 gclass = type->data.generic_class;
3249                 g_assert (gclass->is_dynamic);
3250
3251                 guint32 sig_token = field_encode_signature (assembly, fb, error);
3252                 return_val_if_nok (error, 0);
3253                 name = mono_string_to_utf8_checked (fb->name, error);
3254                 return_val_if_nok (error, 0);
3255                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3256                 g_free (name);          
3257         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3258                 guint32 sig;
3259                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3260
3261                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3262                 return_val_if_nok (error, 0);
3263                 klass = mono_class_from_mono_type (type);
3264
3265                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3266                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3267         } else {
3268                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3269                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3270         }
3271
3272         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3273         return token;
3274 }
3275
3276 static guint32
3277 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3278 {
3279         guint32 sig, token;
3280         MonoClass *klass;
3281         MonoGenericClass *gclass;
3282         MonoType *type;
3283
3284         mono_error_init (error);
3285
3286         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3287
3288         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3289         if (token)
3290                 return token;
3291
3292         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3293                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3294                 ReflectionMethodBuilder rmb;
3295                 char *name;
3296
3297                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3298                 return_val_if_nok (error, 0);
3299                 klass = mono_class_from_mono_type (type);
3300
3301                 gclass = type->data.generic_class;
3302                 g_assert (gclass->is_dynamic);
3303
3304                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3305                         return 0;
3306
3307                 sig = method_builder_encode_signature (assembly, &rmb, error);
3308                 return_val_if_nok (error, 0);
3309
3310                 name = mono_string_to_utf8_checked (rmb.name, error);
3311                 return_val_if_nok (error, 0);
3312
3313                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3314                 g_free (name);
3315         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3316                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3317
3318                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3319                 return_val_if_nok (error, 0);
3320                 klass = mono_class_from_mono_type (type);
3321
3322                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3323                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3324         } else {
3325                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3326                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3327         }
3328
3329
3330         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3331         return token;
3332 }
3333
3334 static MonoMethod*
3335 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3336 {
3337         MonoClass *klass;
3338         MonoGenericContext tmp_context;
3339         MonoType **type_argv;
3340         MonoGenericInst *ginst;
3341         MonoMethod *method, *inflated;
3342         int count, i;
3343
3344         mono_error_init (error);
3345
3346         init_type_builder_generics ((MonoObject*)m->inst, error);
3347         return_val_if_nok (error, NULL);
3348
3349         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3350         return_val_if_nok (error, NULL);
3351
3352         klass = method->klass;
3353
3354         if (m->method_args == NULL)
3355                 return method;
3356
3357         if (method->is_inflated)
3358                 method = ((MonoMethodInflated *) method)->declaring;
3359
3360         count = mono_array_length (m->method_args);
3361
3362         type_argv = g_new0 (MonoType *, count);
3363         for (i = 0; i < count; i++) {
3364                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3365                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3366                 return_val_if_nok (error, NULL);
3367         }
3368         ginst = mono_metadata_get_generic_inst (count, type_argv);
3369         g_free (type_argv);
3370
3371         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3372         tmp_context.method_inst = ginst;
3373
3374         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3375         mono_error_assert_ok (error);
3376         return inflated;
3377 }
3378
3379 static guint32
3380 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3381 {
3382         guint32 sig, token = 0;
3383         MonoType *type;
3384         MonoClass *klass;
3385
3386         mono_error_init (error);
3387
3388         if (m->method_args) {
3389                 MonoMethod *inflated;
3390
3391                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3392                 return_val_if_nok (error, 0);
3393
3394                 if (create_methodspec)
3395                         token = mono_image_get_methodspec_token (assembly, inflated);
3396                 else
3397                         token = mono_image_get_inflated_method_token (assembly, inflated);
3398                 return token;
3399         }
3400
3401         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3402         if (token)
3403                 return token;
3404
3405         if (is_sre_method_builder (mono_object_class (m->mb))) {
3406                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3407                 MonoGenericClass *gclass;
3408                 ReflectionMethodBuilder rmb;
3409                 char *name;
3410
3411                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3412                 return_val_if_nok (error, 0);
3413                 klass = mono_class_from_mono_type (type);
3414                 gclass = type->data.generic_class;
3415                 g_assert (gclass->is_dynamic);
3416
3417                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3418                         return 0;
3419
3420                 sig = method_builder_encode_signature (assembly, &rmb, error);
3421                 return_val_if_nok (error, 0);
3422
3423                 name = mono_string_to_utf8_checked (rmb.name, error);
3424                 return_val_if_nok (error, 0);
3425
3426                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3427                 g_free (name);          
3428         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3429                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3430
3431                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3432                 return_val_if_nok (error, 0);
3433                 klass = mono_class_from_mono_type (type);
3434
3435                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3436                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3437         } else {
3438                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3439                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3440         }
3441
3442         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3443         return token;
3444 }
3445
3446 static guint32
3447 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3448 {
3449         SigBuffer buf;
3450         int i;
3451         guint32 nparams = context->method_inst->type_argc;
3452         guint32 idx;
3453
3454         if (!assembly->save)
3455                 return 0;
3456
3457         sigbuffer_init (&buf, 32);
3458         /*
3459          * FIXME: vararg, explicit_this, differenc call_conv values...
3460          */
3461         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3462         sigbuffer_add_value (&buf, nparams);
3463
3464         for (i = 0; i < nparams; i++)
3465                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3466
3467         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3468         sigbuffer_free (&buf);
3469         return idx;
3470 }
3471
3472 static guint32
3473 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3474 {
3475         MonoDynamicTable *table;
3476         guint32 *values;
3477         guint32 token, mtoken = 0, sig;
3478         MonoMethodInflated *imethod;
3479         MonoMethod *declaring;
3480
3481         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3482
3483         g_assert (method->is_inflated);
3484         imethod = (MonoMethodInflated *) method;
3485         declaring = imethod->declaring;
3486
3487         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3488         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3489
3490         if (!mono_method_signature (declaring)->generic_param_count)
3491                 return mtoken;
3492
3493         switch (mono_metadata_token_table (mtoken)) {
3494         case MONO_TABLE_MEMBERREF:
3495                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3496                 break;
3497         case MONO_TABLE_METHOD:
3498                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3499                 break;
3500         default:
3501                 g_assert_not_reached ();
3502         }
3503
3504         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3505
3506         if (assembly->save) {
3507                 alloc_table (table, table->rows + 1);
3508                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3509                 values [MONO_METHODSPEC_METHOD] = mtoken;
3510                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3511         }
3512
3513         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3514         table->next_idx ++;
3515
3516         return token;
3517 }
3518
3519 static guint32
3520 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3521 {
3522         MonoMethodInflated *imethod;
3523         guint32 token;
3524         
3525         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3526         if (token)
3527                 return token;
3528
3529         g_assert (method->is_inflated);
3530         imethod = (MonoMethodInflated *) method;
3531
3532         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3533                 token = method_encode_methodspec (assembly, method);
3534         } else {
3535                 guint32 sig = method_encode_signature (
3536                         assembly, mono_method_signature (imethod->declaring));
3537                 token = mono_image_get_memberref_token (
3538                         assembly, &method->klass->byval_arg, method->name, sig);
3539         }
3540
3541         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3542         return token;
3543 }
3544
3545 static guint32
3546 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3547 {
3548         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3549         guint32 sig, token;
3550
3551         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3552         token = mono_image_get_memberref_token (
3553                 assembly, &m->klass->byval_arg, m->name, sig);
3554
3555         return token;
3556 }
3557
3558 static guint32
3559 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3560 {
3561         MonoDynamicTable *table;
3562         MonoClass *klass;
3563         MonoType *type;
3564         guint32 *values;
3565         guint32 token;
3566         SigBuffer buf;
3567         int count, i;
3568
3569         /*
3570          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3571          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3572          * Because of this, we must not insert it into the `typeref' hash table.
3573          */
3574         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3575         return_val_if_nok (error, 0);
3576         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3577         if (token)
3578                 return token;
3579
3580         sigbuffer_init (&buf, 32);
3581
3582         g_assert (tb->generic_params);
3583         klass = mono_class_from_mono_type (type);
3584
3585         if (tb->generic_container) {
3586                 if (!mono_reflection_create_generic_class (tb, error))
3587                         goto fail;
3588         }
3589
3590         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3591         g_assert (klass->generic_container);
3592         sigbuffer_add_value (&buf, klass->byval_arg.type);
3593         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3594
3595         count = mono_array_length (tb->generic_params);
3596         sigbuffer_add_value (&buf, count);
3597         for (i = 0; i < count; i++) {
3598                 MonoReflectionGenericParam *gparam;
3599
3600                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3601                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3602                 if (!is_ok (error))
3603                         goto fail;
3604
3605                 encode_type (assembly, gparam_type, &buf);
3606         }
3607
3608         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3609
3610         if (assembly->save) {
3611                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3612                 alloc_table (table, table->rows + 1);
3613                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3614                 values [MONO_TYPESPEC_SIGNATURE] = token;
3615         }
3616         sigbuffer_free (&buf);
3617
3618         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3619         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3620         table->next_idx ++;
3621         return token;
3622 fail:
3623         sigbuffer_free (&buf);
3624         return 0;
3625 }
3626
3627 /*
3628  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3629  */
3630 static MonoType*
3631 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3632 {
3633         int i, count, len, pos;
3634         MonoType *t;
3635
3636         mono_error_init (error);
3637
3638         count = 0;
3639         if (modreq)
3640                 count += mono_array_length (modreq);
3641         if (modopt)
3642                 count += mono_array_length (modopt);
3643
3644         if (count == 0)
3645                 return mono_metadata_type_dup (NULL, type);
3646
3647         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3648         t = (MonoType *)g_malloc (len);
3649         memcpy (t, type, MONO_SIZEOF_TYPE);
3650
3651         t->num_mods = count;
3652         pos = 0;
3653         if (modreq) {
3654                 for (i = 0; i < mono_array_length (modreq); ++i) {
3655                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3656                         if (!is_ok (error))
3657                                 goto fail;
3658                         t->modifiers [pos].required = 1;
3659                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3660                         pos ++;
3661                 }
3662         }
3663         if (modopt) {
3664                 for (i = 0; i < mono_array_length (modopt); ++i) {
3665                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3666                         if (!is_ok (error))
3667                                 goto fail;
3668                         t->modifiers [pos].required = 0;
3669                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3670                         pos ++;
3671                 }
3672         }
3673
3674         return t;
3675 fail:
3676         g_free (t);
3677         return NULL;
3678 }
3679
3680 static void
3681 init_type_builder_generics (MonoObject *type, MonoError *error)
3682 {
3683         MonoReflectionTypeBuilder *tb;
3684
3685         mono_error_init (error);
3686
3687         if (!is_sre_type_builder(mono_object_class (type)))
3688                 return;
3689         tb = (MonoReflectionTypeBuilder *)type;
3690
3691         if (tb && tb->generic_container)
3692                 mono_reflection_create_generic_class (tb, error);
3693 }
3694
3695 static guint32
3696 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3697 {
3698         MonoDynamicTable *table;
3699         MonoType *custom = NULL, *type;
3700         guint32 *values;
3701         guint32 token, pclass, parent, sig;
3702         gchar *name;
3703
3704         mono_error_init (error);
3705
3706         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3707         if (token)
3708                 return token;
3709
3710         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3711         return_val_if_nok (error, 0);
3712         /* FIXME: is this call necessary? */
3713         mono_class_from_mono_type (typeb);
3714
3715         /*FIXME this is one more layer of ugliness due how types are created.*/
3716         init_type_builder_generics (fb->type, error);
3717         return_val_if_nok (error, 0);
3718
3719         /* fb->type does not include the custom modifiers */
3720         /* FIXME: We should do this in one place when a fieldbuilder is created */
3721         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3722         return_val_if_nok (error, 0);
3723
3724         if (fb->modreq || fb->modopt) {
3725                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3726                 return_val_if_nok (error, 0);
3727         }
3728
3729         sig = fieldref_encode_signature (assembly, NULL, type);
3730         g_free (custom);
3731
3732         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3733         return_val_if_nok (error, 0);
3734         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3735         
3736         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3737         parent >>= MONO_TYPEDEFORREF_BITS;
3738
3739         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3740
3741         name = mono_string_to_utf8_checked (fb->name, error);
3742         return_val_if_nok (error, 0);
3743
3744         if (assembly->save) {
3745                 alloc_table (table, table->rows + 1);
3746                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3747                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3748                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3749                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3750         }
3751
3752         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3753         table->next_idx ++;
3754         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3755         g_free (name);
3756         return token;
3757 }
3758
3759 static guint32
3760 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3761 {
3762         SigBuffer buf;
3763         guint32 nargs;
3764         guint32 i, idx;
3765
3766         mono_error_init (error);
3767
3768         if (!assembly->save)
3769                 return 0;
3770
3771         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3772         g_assert (helper->type == 2);
3773
3774         if (helper->arguments)
3775                 nargs = mono_array_length (helper->arguments);
3776         else
3777                 nargs = 0;
3778
3779         sigbuffer_init (&buf, 32);
3780
3781         /* Encode calling convention */
3782         /* Change Any to Standard */
3783         if ((helper->call_conv & 0x03) == 0x03)
3784                 helper->call_conv = 0x01;
3785         /* explicit_this implies has_this */
3786         if (helper->call_conv & 0x40)
3787                 helper->call_conv &= 0x20;
3788
3789         if (helper->call_conv == 0) { /* Unmanaged */
3790                 idx = helper->unmanaged_call_conv - 1;
3791         } else {
3792                 /* Managed */
3793                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3794                 if (helper->call_conv & 0x02) /* varargs */
3795                         idx += 0x05;
3796         }
3797
3798         sigbuffer_add_byte (&buf, idx);
3799         sigbuffer_add_value (&buf, nargs);
3800         encode_reflection_type (assembly, helper->return_type, &buf, error);
3801         if (!is_ok (error))
3802                 goto fail;
3803         for (i = 0; i < nargs; ++i) {
3804                 MonoArray *modreqs = NULL;
3805                 MonoArray *modopts = NULL;
3806                 MonoReflectionType *pt;
3807
3808                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3809                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3810                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3811                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3812
3813                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3814                 if (!is_ok (error))
3815                         goto fail;
3816                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3817                 encode_reflection_type (assembly, pt, &buf, error);
3818                 if (!is_ok (error))
3819                         goto fail;
3820         }
3821         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3822         sigbuffer_free (&buf);
3823
3824         return idx;
3825 fail:
3826         sigbuffer_free (&buf);
3827         return 0;
3828 }
3829
3830 static guint32 
3831 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3832 {
3833         guint32 idx;
3834         MonoDynamicTable *table;
3835         guint32 *values;
3836
3837         mono_error_init (error);
3838
3839         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3840         idx = table->next_idx ++;
3841         table->rows ++;
3842         alloc_table (table, table->rows);
3843         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3844
3845         values [MONO_STAND_ALONE_SIGNATURE] =
3846                 mono_reflection_encode_sighelper (assembly, helper, error);
3847         return_val_if_nok (error, 0);
3848         
3849         return idx;
3850 }
3851
3852 static int
3853 reflection_cc_to_file (int call_conv) {
3854         switch (call_conv & 0x3) {
3855         case 0:
3856         case 1: return MONO_CALL_DEFAULT;
3857         case 2: return MONO_CALL_VARARG;
3858         default:
3859                 g_assert_not_reached ();
3860         }
3861         return 0;
3862 }
3863 #endif /* !DISABLE_REFLECTION_EMIT */
3864
3865 typedef struct {
3866         MonoType *parent;
3867         MonoMethodSignature *sig;
3868         char *name;
3869         guint32 token;
3870 } ArrayMethod;
3871
3872 #ifndef DISABLE_REFLECTION_EMIT
3873 static guint32
3874 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3875 {
3876         guint32 nparams, i;
3877         GList *tmp;
3878         char *name = NULL;
3879         MonoMethodSignature *sig;
3880         ArrayMethod *am = NULL;
3881         MonoType *mtype;
3882
3883         mono_error_init (error);
3884
3885         nparams = mono_array_length (m->parameters);
3886         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3887         sig->hasthis = 1;
3888         sig->sentinelpos = -1;
3889         sig->call_convention = reflection_cc_to_file (m->call_conv);
3890         sig->param_count = nparams;
3891         if (m->ret) {
3892                 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3893                 if (!is_ok (error))
3894                         goto fail;
3895         } else
3896                 sig->ret = &mono_defaults.void_class->byval_arg;
3897
3898         mtype = mono_reflection_type_get_handle (m->parent, error);
3899         if (!is_ok (error))
3900                 goto fail;
3901
3902         for (i = 0; i < nparams; ++i) {
3903                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3904                 if (!is_ok (error))
3905                         goto fail;
3906         }
3907
3908         name = mono_string_to_utf8_checked (m->name, error);
3909         if (!is_ok (error))
3910                 goto fail;
3911         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3912                 am = (ArrayMethod *)tmp->data;
3913                 if (strcmp (name, am->name) == 0 && 
3914                                 mono_metadata_type_equal (am->parent, mtype) &&
3915                                 mono_metadata_signature_equal (am->sig, sig)) {
3916                         g_free (name);
3917                         g_free (sig);
3918                         m->table_idx = am->token & 0xffffff;
3919                         return am->token;
3920                 }
3921         }
3922         am = g_new0 (ArrayMethod, 1);
3923         am->name = name;
3924         am->sig = sig;
3925         am->parent = mtype;
3926         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3927                 method_encode_signature (assembly, sig));
3928         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3929         m->table_idx = am->token & 0xffffff;
3930         return am->token;
3931 fail:
3932         g_free (am);
3933         g_free (name);
3934         g_free (sig);
3935         return 0;
3936
3937 }
3938
3939 /*
3940  * Insert into the metadata tables all the info about the TypeBuilder tb.
3941  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3942  */
3943 static gboolean
3944 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3945 {
3946         MonoDynamicTable *table;
3947         guint *values;
3948         int i, is_object = 0, is_system = 0;
3949         char *n;
3950
3951         mono_error_init (error);
3952
3953         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3954         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3955         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3956         n = mono_string_to_utf8_checked (tb->name, error);
3957         return_val_if_nok (error, FALSE);
3958         if (strcmp (n, "Object") == 0)
3959                 is_object++;
3960         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3961         g_free (n);
3962         n = mono_string_to_utf8_checked (tb->nspace, error);
3963         return_val_if_nok (error, FALSE);
3964         if (strcmp (n, "System") == 0)
3965                 is_system++;
3966         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3967         g_free (n);
3968         if (tb->parent && !(is_system && is_object) && 
3969                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3970                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3971                 return_val_if_nok (error, FALSE);
3972                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3973         } else {
3974                 values [MONO_TYPEDEF_EXTENDS] = 0;
3975         }
3976         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3977         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3978
3979         /*
3980          * if we have explicitlayout or sequentiallayouts, output data in the
3981          * ClassLayout table.
3982          */
3983         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3984                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3985                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3986                 table->rows++;
3987                 alloc_table (table, table->rows);
3988                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3989                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3990                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3991                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3992         }
3993
3994         /* handle interfaces */
3995         if (tb->interfaces) {
3996                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3997                 i = table->rows;
3998                 table->rows += mono_array_length (tb->interfaces);
3999                 alloc_table (table, table->rows);
4000                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
4001                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
4002                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
4003                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
4004                         return_val_if_nok (error, FALSE);
4005                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
4006                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
4007                         values += MONO_INTERFACEIMPL_SIZE;
4008                 }
4009         }
4010
4011         /* handle fields */
4012         if (tb->fields) {
4013                 table = &assembly->tables [MONO_TABLE_FIELD];
4014                 table->rows += tb->num_fields;
4015                 alloc_table (table, table->rows);
4016                 for (i = 0; i < tb->num_fields; ++i) {
4017                         mono_image_get_field_info (
4018                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
4019                         return_val_if_nok (error, FALSE);
4020                 }
4021         }
4022
4023         /* handle constructors */
4024         if (tb->ctors) {
4025                 table = &assembly->tables [MONO_TABLE_METHOD];
4026                 table->rows += mono_array_length (tb->ctors);
4027                 alloc_table (table, table->rows);
4028                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4029                         if (!mono_image_get_ctor_info (domain,
4030                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
4031                                                        assembly, error))
4032                                 return FALSE;
4033                 }
4034         }
4035
4036         /* handle methods */
4037         if (tb->methods) {
4038                 table = &assembly->tables [MONO_TABLE_METHOD];
4039                 table->rows += tb->num_methods;
4040                 alloc_table (table, table->rows);
4041                 for (i = 0; i < tb->num_methods; ++i) {
4042                         if (!mono_image_get_method_info (
4043                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4044                                 return FALSE;
4045                 }
4046         }
4047
4048         /* Do the same with properties etc.. */
4049         if (tb->events && mono_array_length (tb->events)) {
4050                 table = &assembly->tables [MONO_TABLE_EVENT];
4051                 table->rows += mono_array_length (tb->events);
4052                 alloc_table (table, table->rows);
4053                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4054                 table->rows ++;
4055                 alloc_table (table, table->rows);
4056                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4057                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4058                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4059                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4060                         mono_image_get_event_info (
4061                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4062                         return_val_if_nok (error, FALSE);
4063                 }
4064         }
4065         if (tb->properties && mono_array_length (tb->properties)) {
4066                 table = &assembly->tables [MONO_TABLE_PROPERTY];
4067                 table->rows += mono_array_length (tb->properties);
4068                 alloc_table (table, table->rows);
4069                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4070                 table->rows ++;
4071                 alloc_table (table, table->rows);
4072                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4073                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4074                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4075                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4076                         mono_image_get_property_info (
4077                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4078                         return_val_if_nok (error, FALSE);
4079                 }
4080         }
4081
4082         /* handle generic parameters */
4083         if (tb->generic_params) {
4084                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4085                 table->rows += mono_array_length (tb->generic_params);
4086                 alloc_table (table, table->rows);
4087                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4088                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4089
4090                         mono_image_get_generic_param_info (
4091                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4092                 }
4093         }
4094
4095         mono_image_add_decl_security (assembly, 
4096                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4097
4098         if (tb->subtypes) {
4099                 MonoDynamicTable *ntable;
4100                 
4101                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4102                 ntable->rows += mono_array_length (tb->subtypes);
4103                 alloc_table (ntable, ntable->rows);
4104                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4105
4106                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4107                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4108
4109                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4110                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4111                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4112                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4113                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4114                                 ntable->next_idx, ntable->rows);*/
4115                         values += MONO_NESTED_CLASS_SIZE;
4116                         ntable->next_idx++;
4117                 }
4118         }
4119
4120         return TRUE;
4121 }
4122 #endif
4123
4124 static void
4125 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4126 {
4127         int i;
4128
4129         mono_ptr_array_append (*types, type);
4130
4131         if (!type->subtypes)
4132                 return;
4133
4134         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4135                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4136                 collect_types (types, subtype);
4137         }
4138 }
4139
4140 static gint
4141 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4142 {
4143         if ((*type1)->table_idx < (*type2)->table_idx)
4144                 return -1;
4145         else
4146                 if ((*type1)->table_idx > (*type2)->table_idx)
4147                         return 1;
4148         else
4149                 return 0;
4150 }
4151
4152 static gboolean
4153 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4154         int i;
4155
4156         mono_error_init (error);
4157         if (!pinfo)
4158                 return TRUE;
4159         for (i = 0; i < mono_array_length (pinfo); ++i) {
4160                 MonoReflectionParamBuilder *pb;
4161                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4162                 if (!pb)
4163                         continue;
4164                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4165                         return FALSE;
4166         }
4167
4168         return TRUE;
4169 }
4170
4171 static gboolean
4172 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4173         int i;
4174
4175         mono_error_init (error);
4176         
4177         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4178                 return FALSE;
4179         if (tb->fields) {
4180                 for (i = 0; i < tb->num_fields; ++i) {
4181                         MonoReflectionFieldBuilder* fb;
4182                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4183                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4184                                 return FALSE;
4185                 }
4186         }
4187         if (tb->events) {
4188                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4189                         MonoReflectionEventBuilder* eb;
4190                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4191                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4192                                 return FALSE;
4193                 }
4194         }
4195         if (tb->properties) {
4196                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4197                         MonoReflectionPropertyBuilder* pb;
4198                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4199                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4200                                 return FALSE;
4201                 }
4202         }
4203         if (tb->ctors) {
4204                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4205                         MonoReflectionCtorBuilder* cb;
4206                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4207                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4208                             !params_add_cattrs (assembly, cb->pinfo, error))
4209                                 return FALSE;
4210                 }
4211         }
4212
4213         if (tb->methods) {
4214                 for (i = 0; i < tb->num_methods; ++i) {
4215                         MonoReflectionMethodBuilder* mb;
4216                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4217                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4218                             !params_add_cattrs (assembly, mb->pinfo, error))
4219                                 return FALSE;
4220                 }
4221         }
4222
4223         if (tb->subtypes) {
4224                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4225                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4226                                 return FALSE;
4227                 }
4228         }
4229
4230         return TRUE;
4231 }
4232
4233 static gboolean
4234 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4235 {
4236         int i;
4237         
4238         mono_error_init (error);
4239
4240         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4241                 return FALSE;
4242
4243         if (moduleb->global_methods) {
4244                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4245                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4246                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4247                             !params_add_cattrs (assembly, mb->pinfo, error))
4248                                 return FALSE;
4249                 }
4250         }
4251
4252         if (moduleb->global_fields) {
4253                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4254                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4255                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4256                                 return FALSE;
4257                 }
4258         }
4259         
4260         if (moduleb->types) {
4261                 for (i = 0; i < moduleb->num_types; ++i) {
4262                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4263                                 return FALSE;
4264                 }
4265         }
4266
4267         return TRUE;
4268 }
4269
4270 static void
4271 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4272 {
4273         MonoError error;
4274         MonoDynamicTable *table;
4275         guint32 *values;
4276         char blob_size [6];
4277         guchar hash [20];
4278         char *b = blob_size;
4279         char *dir, *path;
4280
4281         table = &assembly->tables [MONO_TABLE_FILE];
4282         table->rows++;
4283         alloc_table (table, table->rows);
4284         values = table->values + table->next_idx * MONO_FILE_SIZE;
4285         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4286         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4287         if (image_is_dynamic (module->image)) {
4288                 /* This depends on the fact that the main module is emitted last */
4289                 dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, &error);
4290                 mono_error_raise_exception (&error); /* FIXME don't raise here */
4291                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4292         } else {
4293                 dir = NULL;
4294                 path = g_strdup (module->image->name);
4295         }
4296         mono_sha1_get_digest_from_file (path, hash);
4297         g_free (dir);
4298         g_free (path);
4299         mono_metadata_encode_value (20, b, &b);
4300         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4301         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4302         table->next_idx ++;
4303 }
4304
4305 static void
4306 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4307 {
4308         MonoDynamicTable *table;
4309         int i;
4310
4311         table = &assembly->tables [MONO_TABLE_MODULE];
4312         mb->table_idx = table->next_idx ++;
4313         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4314         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4315         i /= 16;
4316         ++i;
4317         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4318         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4319         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4320         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4321 }
4322
4323 static guint32
4324 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4325         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4326 {
4327         MonoDynamicTable *table;
4328         guint32 *values;
4329         guint32 visib, res;
4330
4331         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4332         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4333                 return 0;
4334
4335         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4336         table->rows++;
4337         alloc_table (table, table->rows);
4338         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4339
4340         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4341         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4342         if (klass->nested_in)
4343                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4344         else
4345                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4346         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4347         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4348
4349         res = table->next_idx;
4350
4351         table->next_idx ++;
4352
4353         /* Emit nested types */
4354         if (klass->ext && klass->ext->nested_classes) {
4355                 GList *tmp;
4356
4357                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4358                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4359         }
4360
4361         return res;
4362 }
4363
4364 static void
4365 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4366                               guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4367                               MonoError *error)
4368 {
4369         MonoClass *klass;
4370         guint32 idx, i;
4371
4372         mono_error_init (error);
4373
4374         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4375         return_if_nok (error);
4376
4377         klass = mono_class_from_mono_type (t);
4378
4379         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4380
4381         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4382                                                                                                    parent_index, assembly);
4383
4384         /* 
4385          * Emit nested types
4386          * We need to do this ourselves since klass->nested_classes is not set up.
4387          */
4388         if (tb->subtypes) {
4389                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4390                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4391                         return_if_nok (error);
4392                 }
4393         }
4394 }
4395
4396 static void
4397 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4398         guint32 module_index, MonoDynamicImage *assembly)
4399 {
4400         MonoImage *image = module->image;
4401         MonoTableInfo  *t;
4402         guint32 i;
4403
4404         t = &image->tables [MONO_TABLE_TYPEDEF];
4405
4406         for (i = 0; i < t->rows; ++i) {
4407                 MonoError error;
4408                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4409                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4410
4411                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4412                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4413         }
4414 }
4415
4416 static void
4417 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4418 {
4419         MonoDynamicTable *table;
4420         guint32 *values;
4421         guint32 scope, scope_idx, impl, current_idx;
4422         gboolean forwarder = TRUE;
4423         gpointer iter = NULL;
4424         MonoClass *nested;
4425
4426         if (klass->nested_in) {
4427                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4428                 forwarder = FALSE;
4429         } else {
4430                 scope = resolution_scope_from_image (assembly, klass->image);
4431                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4432                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4433                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4434         }
4435
4436         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4437
4438         table->rows++;
4439         alloc_table (table, table->rows);
4440         current_idx = table->next_idx;
4441         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4442
4443         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4444         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4445         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4446         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4447         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4448
4449         table->next_idx++;
4450
4451         while ((nested = mono_class_get_nested_types (klass, &iter)))
4452                 add_exported_type (assemblyb, assembly, nested, current_idx);
4453 }
4454
4455 static void
4456 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4457 {
4458         MonoError error;
4459         MonoClass *klass;
4460         int i;
4461
4462         if (!assemblyb->type_forwarders)
4463                 return;
4464
4465         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4466                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4467                 MonoType *type;
4468                 if (!t)
4469                         continue;
4470
4471                 type = mono_reflection_type_get_handle (t, &error);
4472                 mono_error_assert_ok (&error);
4473                 g_assert (type);
4474
4475                 klass = mono_class_from_mono_type (type);
4476
4477                 add_exported_type (assemblyb, assembly, klass, 0);
4478         }
4479 }
4480
4481 #define align_pointer(base,p)\
4482         do {\
4483                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4484                 if (__diff & 3)\
4485                         (p) += 4 - (__diff & 3);\
4486         } while (0)
4487
4488 static int
4489 compare_constants (const void *a, const void *b)
4490 {
4491         const guint32 *a_values = (const guint32 *)a;
4492         const guint32 *b_values = (const guint32 *)b;
4493         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4494 }
4495
4496 static int
4497 compare_semantics (const void *a, const void *b)
4498 {
4499         const guint32 *a_values = (const guint32 *)a;
4500         const guint32 *b_values = (const guint32 *)b;
4501         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4502         if (assoc)
4503                 return assoc;
4504         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4505 }
4506
4507 static int
4508 compare_custom_attrs (const void *a, const void *b)
4509 {
4510         const guint32 *a_values = (const guint32 *)a;
4511         const guint32 *b_values = (const guint32 *)b;
4512
4513         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4514 }
4515
4516 static int
4517 compare_field_marshal (const void *a, const void *b)
4518 {
4519         const guint32 *a_values = (const guint32 *)a;
4520         const guint32 *b_values = (const guint32 *)b;
4521
4522         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4523 }
4524
4525 static int
4526 compare_nested (const void *a, const void *b)
4527 {
4528         const guint32 *a_values = (const guint32 *)a;
4529         const guint32 *b_values = (const guint32 *)b;
4530
4531         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4532 }
4533
4534 static int
4535 compare_genericparam (const void *a, const void *b)
4536 {
4537         MonoError error;
4538         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4539         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4540
4541         if ((*b_entry)->owner == (*a_entry)->owner) {
4542                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4543                 mono_error_assert_ok (&error);
4544                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4545                 mono_error_assert_ok (&error);
4546                 return 
4547                         mono_type_get_generic_param_num (a_type) -
4548                         mono_type_get_generic_param_num (b_type);
4549         } else
4550                 return (*a_entry)->owner - (*b_entry)->owner;
4551 }
4552
4553 static int
4554 compare_declsecurity_attrs (const void *a, const void *b)
4555 {
4556         const guint32 *a_values = (const guint32 *)a;
4557         const guint32 *b_values = (const guint32 *)b;
4558
4559         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4560 }
4561
4562 static int
4563 compare_interface_impl (const void *a, const void *b)
4564 {
4565         const guint32 *a_values = (const guint32 *)a;
4566         const guint32 *b_values = (const guint32 *)b;
4567
4568         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4569         if (klass)
4570                 return klass;
4571
4572         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4573 }
4574
4575 static void
4576 pad_heap (MonoDynamicStream *sh)
4577 {
4578         if (sh->index & 3) {
4579                 int sz = 4 - (sh->index & 3);
4580                 memset (sh->data + sh->index, 0, sz);
4581                 sh->index += sz;
4582         }
4583 }
4584
4585 struct StreamDesc {
4586         const char *name;
4587         MonoDynamicStream *stream;
4588 };
4589
4590 /*
4591  * build_compressed_metadata() fills in the blob of data that represents the 
4592  * raw metadata as it will be saved in the PE file. The five streams are output 
4593  * and the metadata tables are comnpressed from the guint32 array representation, 
4594  * to the compressed on-disk format.
4595  */
4596 static gboolean
4597 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4598 {
4599         MonoDynamicTable *table;
4600         int i;
4601         guint64 valid_mask = 0;
4602         guint64 sorted_mask;
4603         guint32 heapt_size = 0;
4604         guint32 meta_size = 256; /* allow for header and other stuff */
4605         guint32 table_offset;
4606         guint32 ntables = 0;
4607         guint64 *int64val;
4608         guint32 *int32val;
4609         guint16 *int16val;
4610         MonoImage *meta;
4611         unsigned char *p;
4612         struct StreamDesc stream_desc [5];
4613
4614         mono_error_init (error);
4615
4616         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4617         for (i = 0; i < assembly->gen_params->len; i++) {
4618                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4619                 if (!write_generic_param_entry (assembly, entry, error))
4620                         return FALSE;
4621         }
4622
4623         stream_desc [0].name  = "#~";
4624         stream_desc [0].stream = &assembly->tstream;
4625         stream_desc [1].name  = "#Strings";
4626         stream_desc [1].stream = &assembly->sheap;
4627         stream_desc [2].name  = "#US";
4628         stream_desc [2].stream = &assembly->us;
4629         stream_desc [3].name  = "#Blob";
4630         stream_desc [3].stream = &assembly->blob;
4631         stream_desc [4].name  = "#GUID";
4632         stream_desc [4].stream = &assembly->guid;
4633         
4634         /* tables that are sorted */
4635         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4636                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4637                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4638                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4639                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4640                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4641                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4642         
4643         /* Compute table sizes */
4644         /* the MonoImage has already been created in mono_image_basic_init() */
4645         meta = &assembly->image;
4646
4647         /* sizes should be multiple of 4 */
4648         pad_heap (&assembly->blob);
4649         pad_heap (&assembly->guid);
4650         pad_heap (&assembly->sheap);
4651         pad_heap (&assembly->us);
4652
4653         /* Setup the info used by compute_sizes () */
4654         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4655         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4656         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4657
4658         meta_size += assembly->blob.index;
4659         meta_size += assembly->guid.index;
4660         meta_size += assembly->sheap.index;
4661         meta_size += assembly->us.index;
4662
4663         for (i=0; i < MONO_TABLE_NUM; ++i)
4664                 meta->tables [i].rows = assembly->tables [i].rows;
4665         
4666         for (i = 0; i < MONO_TABLE_NUM; i++){
4667                 if (meta->tables [i].rows == 0)
4668                         continue;
4669                 valid_mask |= (guint64)1 << i;
4670                 ntables ++;
4671                 meta->tables [i].row_size = mono_metadata_compute_size (
4672                         meta, i, &meta->tables [i].size_bitfield);
4673                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4674         }
4675         heapt_size += 24; /* #~ header size */
4676         heapt_size += ntables * 4;
4677         /* make multiple of 4 */
4678         heapt_size += 3;
4679         heapt_size &= ~3;
4680         meta_size += heapt_size;
4681         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4682         p = (unsigned char*)meta->raw_metadata;
4683         /* the metadata signature */
4684         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4685         /* version numbers and 4 bytes reserved */
4686         int16val = (guint16*)p;
4687         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4688         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4689         p += 8;
4690         /* version string */
4691         int32val = (guint32*)p;
4692         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4693         p += 4;
4694         memcpy (p, meta->version, strlen (meta->version));
4695         p += GUINT32_FROM_LE (*int32val);
4696         align_pointer (meta->raw_metadata, p);
4697         int16val = (guint16*)p;
4698         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4699         *int16val = GUINT16_TO_LE (5); /* number of streams */
4700         p += 4;
4701
4702         /*
4703          * write the stream info.
4704          */
4705         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4706         table_offset += 3; table_offset &= ~3;
4707
4708         assembly->tstream.index = heapt_size;
4709         for (i = 0; i < 5; ++i) {
4710                 int32val = (guint32*)p;
4711                 stream_desc [i].stream->offset = table_offset;
4712                 *int32val++ = GUINT32_TO_LE (table_offset);
4713                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4714                 table_offset += GUINT32_FROM_LE (*int32val);
4715                 table_offset += 3; table_offset &= ~3;
4716                 p += 8;
4717                 strcpy ((char*)p, stream_desc [i].name);
4718                 p += strlen (stream_desc [i].name) + 1;
4719                 align_pointer (meta->raw_metadata, p);
4720         }
4721         /* 
4722          * now copy the data, the table stream header and contents goes first.
4723          */
4724         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4725         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4726         int32val = (guint32*)p;
4727         *int32val = GUINT32_TO_LE (0); /* reserved */
4728         p += 4;
4729
4730         *p++ = 2; /* version */
4731         *p++ = 0;
4732
4733         if (meta->idx_string_wide)
4734                 *p |= 0x01;
4735         if (meta->idx_guid_wide)
4736                 *p |= 0x02;
4737         if (meta->idx_blob_wide)
4738                 *p |= 0x04;
4739         ++p;
4740         *p++ = 1; /* reserved */
4741         int64val = (guint64*)p;
4742         *int64val++ = GUINT64_TO_LE (valid_mask);
4743         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4744         p += 16;
4745         int32val = (guint32*)p;
4746         for (i = 0; i < MONO_TABLE_NUM; i++){
4747                 if (meta->tables [i].rows == 0)
4748                         continue;
4749                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4750         }
4751         p = (unsigned char*)int32val;
4752
4753         /* sort the tables that still need sorting */
4754         table = &assembly->tables [MONO_TABLE_CONSTANT];
4755         if (table->rows)
4756                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4757         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4758         if (table->rows)
4759                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4760         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4761         if (table->rows)
4762                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4763         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4764         if (table->rows)
4765                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4766         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4767         if (table->rows)
4768                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4769         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4770         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4771         if (table->rows)
4772                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4773         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4774         if (table->rows)
4775                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4776
4777         /* compress the tables */
4778         for (i = 0; i < MONO_TABLE_NUM; i++){
4779                 int row, col;
4780                 guint32 *values;
4781                 guint32 bitfield = meta->tables [i].size_bitfield;
4782                 if (!meta->tables [i].rows)
4783                         continue;
4784                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4785                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4786                 meta->tables [i].base = (char*)p;
4787                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4788                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4789                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4790                                 switch (mono_metadata_table_size (bitfield, col)) {
4791                                 case 1:
4792                                         *p++ = values [col];
4793                                         break;
4794                                 case 2:
4795                                         *p++ = values [col] & 0xff;
4796                                         *p++ = (values [col] >> 8) & 0xff;
4797                                         break;
4798                                 case 4:
4799                                         *p++ = values [col] & 0xff;
4800                                         *p++ = (values [col] >> 8) & 0xff;
4801                                         *p++ = (values [col] >> 16) & 0xff;
4802                                         *p++ = (values [col] >> 24) & 0xff;
4803                                         break;
4804                                 default:
4805                                         g_assert_not_reached ();
4806                                 }
4807                         }
4808                 }
4809                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4810         }
4811         
4812         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4813         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4814         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4815         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4816         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4817
4818         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4819
4820         return TRUE;
4821 }
4822
4823 /*
4824  * Some tables in metadata need to be sorted according to some criteria, but
4825  * when methods and fields are first created with reflection, they may be assigned a token
4826  * that doesn't correspond to the final token they will get assigned after the sorting.
4827  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4828  * with the reflection objects that represent them. Once all the tables are set up, the 
4829  * reflection objects will contains the correct table index. fixup_method() will fixup the
4830  * tokens for the method with ILGenerator @ilgen.
4831  */
4832 static void
4833 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4834 {
4835         guint32 code_idx = GPOINTER_TO_UINT (value);
4836         MonoReflectionILTokenInfo *iltoken;
4837         MonoReflectionFieldBuilder *field;
4838         MonoReflectionCtorBuilder *ctor;
4839         MonoReflectionMethodBuilder *method;
4840         MonoReflectionTypeBuilder *tb;
4841         MonoReflectionArrayMethod *am;
4842         guint32 i, idx = 0;
4843         unsigned char *target;
4844
4845         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4846                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4847                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4848                 switch (target [3]) {
4849                 case MONO_TABLE_FIELD:
4850                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4851                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4852                                 idx = field->table_idx;
4853                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4854                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4855                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4856                         } else {
4857                                 g_assert_not_reached ();
4858                         }
4859                         break;
4860                 case MONO_TABLE_METHOD:
4861                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4862                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4863                                 idx = method->table_idx;
4864                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4865                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4866                                 idx = ctor->table_idx;
4867                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4868                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4869                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4870                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4871                         } else {
4872                                 g_assert_not_reached ();
4873                         }
4874                         break;
4875                 case MONO_TABLE_TYPEDEF:
4876                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4877                                 g_assert_not_reached ();
4878                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4879                         idx = tb->table_idx;
4880                         break;
4881                 case MONO_TABLE_MEMBERREF:
4882                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4883                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4884                                 idx = am->table_idx;
4885                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4886                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4887                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4888                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4889                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4890                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4891                                 continue;
4892                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4893                                 continue;
4894                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4895                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4896                                 g_assert (is_field_on_inst (f));
4897                                 continue;
4898                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4899                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4900                                 continue;
4901                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4902                                 continue;
4903                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4904                                 continue;
4905                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4906                                 continue;
4907                         } else {
4908                                 g_assert_not_reached ();
4909                         }
4910                         break;
4911                 case MONO_TABLE_METHODSPEC:
4912                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4913                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4914                                 g_assert (mono_method_signature (m)->generic_param_count);
4915                                 continue;
4916                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4917                                 continue;
4918                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4919                                 continue;
4920                         } else {
4921                                 g_assert_not_reached ();
4922                         }
4923                         break;
4924                 default:
4925                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4926                 }
4927                 target [0] = idx & 0xff;
4928                 target [1] = (idx >> 8) & 0xff;
4929                 target [2] = (idx >> 16) & 0xff;
4930         }
4931 }
4932
4933 /*
4934  * fixup_cattrs:
4935  *
4936  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4937  * value is not known when the table is emitted.
4938  */
4939 static void
4940 fixup_cattrs (MonoDynamicImage *assembly)
4941 {
4942         MonoDynamicTable *table;
4943         guint32 *values;
4944         guint32 type, i, idx, token;
4945         MonoObject *ctor;
4946
4947         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4948
4949         for (i = 0; i < table->rows; ++i) {
4950                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4951
4952                 type = values [MONO_CUSTOM_ATTR_TYPE];
4953                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4954                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4955                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4956                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4957                         g_assert (ctor);
4958
4959                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4960                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4961                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4962                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4963                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4964                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4965                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4966                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4967                         }
4968                 }
4969         }
4970 }
4971
4972 static void
4973 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4974 {
4975         MonoDynamicTable *table;
4976         guint32 *values;
4977
4978         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4979         table->rows++;
4980         alloc_table (table, table->rows);
4981         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4982         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4983         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4984         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4985         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4986         table->next_idx++;
4987 }
4988
4989 static void
4990 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4991 {
4992         MonoError error;
4993         MonoDynamicTable *table;
4994         guint32 *values;
4995         char blob_size [6];
4996         guchar hash [20];
4997         char *b = blob_size;
4998         char *name, *sname;
4999         guint32 idx, offset;
5000
5001         if (rsrc->filename) {
5002                 name = mono_string_to_utf8_checked (rsrc->filename, &error);
5003                 mono_error_raise_exception (&error); /* FIXME don't raise here */
5004                 sname = g_path_get_basename (name);
5005         
5006                 table = &assembly->tables [MONO_TABLE_FILE];
5007                 table->rows++;
5008                 alloc_table (table, table->rows);
5009                 values = table->values + table->next_idx * MONO_FILE_SIZE;
5010                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
5011                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
5012                 g_free (sname);
5013
5014                 mono_sha1_get_digest_from_file (name, hash);
5015                 mono_metadata_encode_value (20, b, &b);
5016                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
5017                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
5018                 g_free (name);
5019                 idx = table->next_idx++;
5020                 rsrc->offset = 0;
5021                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
5022         } else {
5023                 char sizebuf [4];
5024                 char *data;
5025                 guint len;
5026                 if (rsrc->data) {
5027                         data = mono_array_addr (rsrc->data, char, 0);
5028                         len = mono_array_length (rsrc->data);
5029                 } else {
5030                         data = NULL;
5031                         len = 0;
5032                 }
5033                 offset = len;
5034                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
5035                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
5036                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
5037                 mono_image_add_stream_data (&assembly->resources, data, len);
5038
5039                 if (!mb->is_main)
5040                         /* 
5041                          * The entry should be emitted into the MANIFESTRESOURCE table of 
5042                          * the main module, but that needs to reference the FILE table
5043                          * which isn't emitted yet.
5044                          */
5045                         return;
5046                 else
5047                         idx = 0;
5048         }
5049
5050         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5051 }
5052
5053 static void
5054 set_version_from_string (MonoString *version, guint32 *values)
5055 {
5056         MonoError error;
5057         gchar *ver, *p, *str;
5058         guint32 i;
5059         
5060         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5061         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5062         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5063         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5064         if (!version)
5065                 return;
5066         ver = str = mono_string_to_utf8_checked (version, &error);
5067         mono_error_raise_exception (&error); /* FIXME don't raise here */
5068         for (i = 0; i < 4; ++i) {
5069                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5070                 switch (*p) {
5071                 case '.':
5072                         p++;
5073                         break;
5074                 case '*':
5075                         /* handle Revision and Build */
5076                         p++;
5077                         break;
5078                 }
5079                 ver = p;
5080         }
5081         g_free (str);
5082 }
5083
5084 static guint32
5085 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5086         gsize len;
5087         guint32 token = 0;
5088         char blob_size [6];
5089         char *b = blob_size;
5090
5091         if (!pkey)
5092                 return token;
5093
5094         len = mono_array_length (pkey);
5095         mono_metadata_encode_value (len, b, &b);
5096         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5097         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5098
5099         assembly->public_key = (guint8 *)g_malloc (len);
5100         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5101         assembly->public_key_len = len;
5102
5103         /* Special case: check for ECMA key (16 bytes) */
5104         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5105                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5106                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5107         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5108                 /* minimum key size (in 2.0) is 384 bits */
5109                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5110         } else {
5111                 /* FIXME - verifier */
5112                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5113                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5114         }
5115         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5116
5117         return token;
5118 }
5119
5120 static void
5121 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5122 {
5123         MonoDynamicTable *table;
5124         MonoDynamicImage *assembly;
5125         MonoReflectionAssemblyBuilder *assemblyb;
5126         MonoDomain *domain;
5127         guint32 *values;
5128         int i;
5129         guint32 module_index;
5130
5131         mono_error_init (error);
5132
5133         assemblyb = moduleb->assemblyb;
5134         assembly = moduleb->dynamic_image;
5135         domain = mono_object_domain (assemblyb);
5136
5137         /* Emit ASSEMBLY table */
5138         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5139         alloc_table (table, 1);
5140         values = table->values + MONO_ASSEMBLY_SIZE;
5141         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5142         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5143         if (assemblyb->culture) {
5144                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5145         } else {
5146                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5147         }
5148         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5149         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5150         set_version_from_string (assemblyb->version, values);
5151
5152         /* Emit FILE + EXPORTED_TYPE table */
5153         module_index = 0;
5154         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5155                 int j;
5156                 MonoReflectionModuleBuilder *file_module = 
5157                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5158                 if (file_module != moduleb) {
5159                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5160                         module_index ++;
5161                         if (file_module->types) {
5162                                 for (j = 0; j < file_module->num_types; ++j) {
5163                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5164                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5165                                         return_if_nok (error);
5166                                 }
5167                         }
5168                 }
5169         }
5170         if (assemblyb->loaded_modules) {
5171                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5172                         MonoReflectionModule *file_module = 
5173                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5174                         mono_image_fill_file_table (domain, file_module, assembly);
5175                         module_index ++;
5176                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5177                 }
5178         }
5179         if (assemblyb->type_forwarders)
5180                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5181
5182         /* Emit MANIFESTRESOURCE table */
5183         module_index = 0;
5184         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5185                 int j;
5186                 MonoReflectionModuleBuilder *file_module = 
5187                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5188                 /* The table for the main module is emitted later */
5189                 if (file_module != moduleb) {
5190                         module_index ++;
5191                         if (file_module->resources) {
5192                                 int len = mono_array_length (file_module->resources);
5193                                 for (j = 0; j < len; ++j) {
5194                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5195                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5196                                 }
5197                         }
5198                 }
5199         }               
5200 }
5201
5202 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5203
5204 /*
5205  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5206  * for the modulebuilder @moduleb.
5207  * At the end of the process, method and field tokens are fixed up and the 
5208  * on-disk compressed metadata representation is created.
5209  * Return TRUE on success, or FALSE on failure and sets @error
5210  */
5211 gboolean
5212 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5213 {
5214         MonoDynamicTable *table;
5215         MonoDynamicImage *assembly;
5216         MonoReflectionAssemblyBuilder *assemblyb;
5217         MonoDomain *domain;
5218         MonoPtrArray types;
5219         guint32 *values;
5220         int i, j;
5221
5222         mono_error_init (error);
5223
5224         assemblyb = moduleb->assemblyb;
5225         assembly = moduleb->dynamic_image;
5226         domain = mono_object_domain (assemblyb);
5227
5228         if (assembly->text_rva)
5229                 return TRUE;
5230
5231         assembly->text_rva = START_TEXT_RVA;
5232
5233         if (moduleb->is_main) {
5234                 mono_image_emit_manifest (moduleb, error);
5235                 return_val_if_nok (error, FALSE);
5236         }
5237
5238         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5239         table->rows = 1; /* .<Module> */
5240         table->next_idx++;
5241         alloc_table (table, table->rows);
5242         /*
5243          * Set the first entry.
5244          */
5245         values = table->values + table->columns;
5246         values [MONO_TYPEDEF_FLAGS] = 0;
5247         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5248         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5249         values [MONO_TYPEDEF_EXTENDS] = 0;
5250         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5251         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5252
5253         /* 
5254          * handle global methods 
5255          * FIXME: test what to do when global methods are defined in multiple modules.
5256          */
5257         if (moduleb->global_methods) {
5258                 table = &assembly->tables [MONO_TABLE_METHOD];
5259                 table->rows += mono_array_length (moduleb->global_methods);
5260                 alloc_table (table, table->rows);
5261                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5262                         if (!mono_image_get_method_info (
5263                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5264                                 goto leave;
5265                 }
5266         }
5267         if (moduleb->global_fields) {
5268                 table = &assembly->tables [MONO_TABLE_FIELD];
5269                 table->rows += mono_array_length (moduleb->global_fields);
5270                 alloc_table (table, table->rows);
5271                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5272                         mono_image_get_field_info (
5273                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5274                                 error);
5275                         if (!is_ok (error))
5276                                 goto leave;
5277                 }
5278         }
5279
5280         table = &assembly->tables [MONO_TABLE_MODULE];
5281         alloc_table (table, 1);
5282         mono_image_fill_module_table (domain, moduleb, assembly);
5283
5284         /* Collect all types into a list sorted by their table_idx */
5285         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5286
5287         if (moduleb->types)
5288                 for (i = 0; i < moduleb->num_types; ++i) {
5289                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5290                         collect_types (&types, type);
5291                 }
5292
5293         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5294         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5295         table->rows += mono_ptr_array_size (types);
5296         alloc_table (table, table->rows);
5297
5298         /*
5299          * Emit type names + namespaces at one place inside the string heap,
5300          * so load_class_names () needs to touch fewer pages.
5301          */
5302         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5303                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5304                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5305         }
5306         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5307                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5308                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5309         }
5310
5311         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5312                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5313                 if (!mono_image_get_type_info (domain, type, assembly, error))
5314                         goto leave_types;
5315         }
5316
5317         /* 
5318          * table->rows is already set above and in mono_image_fill_module_table.
5319          */
5320         /* add all the custom attributes at the end, once all the indexes are stable */
5321         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5322                 goto leave_types;
5323
5324         /* CAS assembly permissions */
5325         if (assemblyb->permissions_minimum)
5326                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5327         if (assemblyb->permissions_optional)
5328                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5329         if (assemblyb->permissions_refused)
5330                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5331
5332         if (!module_add_cattrs (assembly, moduleb, error))
5333                 goto leave_types;
5334
5335         /* fixup tokens */
5336         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5337
5338         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5339          * the final tokens and don't need another fixup pass. */
5340
5341         if (moduleb->global_methods) {
5342                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5343                         MonoReflectionMethodBuilder *mb = mono_array_get (
5344                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5345                         if (!mono_image_add_methodimpl (assembly, mb, error))
5346                                 goto leave_types;
5347                 }
5348         }
5349
5350         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5351                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5352                 if (type->methods) {
5353                         for (j = 0; j < type->num_methods; ++j) {
5354                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5355                                         type->methods, MonoReflectionMethodBuilder*, j);
5356
5357                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5358                                         goto leave_types;
5359                         }
5360                 }
5361         }
5362
5363         fixup_cattrs (assembly);
5364
5365 leave_types:
5366         mono_ptr_array_destroy (types);
5367 leave:
5368
5369         return mono_error_ok (error);
5370 }
5371
5372 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5373
5374 gboolean
5375 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5376 {
5377         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5378 }
5379
5380 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5381
5382
5383 typedef struct {
5384         guint32 import_lookup_table;
5385         guint32 timestamp;
5386         guint32 forwarder;
5387         guint32 name_rva;
5388         guint32 import_address_table_rva;
5389 } MonoIDT;
5390
5391 typedef struct {
5392         guint32 name_rva;
5393         guint32 flags;
5394 } MonoILT;
5395
5396 #ifndef DISABLE_REFLECTION_EMIT
5397
5398 /*
5399  * mono_image_insert_string:
5400  * @module: module builder object
5401  * @str: a string
5402  *
5403  * Insert @str into the user string stream of @module.
5404  */
5405 guint32
5406 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5407 {
5408         MonoDynamicImage *assembly;
5409         guint32 idx;
5410         char buf [16];
5411         char *b = buf;
5412         
5413         if (!module->dynamic_image)
5414                 mono_image_module_basic_init (module);
5415
5416         assembly = module->dynamic_image;
5417         
5418         if (assembly->save) {
5419                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5420                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5421 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5422         {
5423                 char *swapped = g_malloc (2 * mono_string_length (str));
5424                 const char *p = (const char*)mono_string_chars (str);
5425
5426                 swap_with_size (swapped, p, 2, mono_string_length (str));
5427                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5428                 g_free (swapped);
5429         }
5430 #else
5431                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5432 #endif
5433                 mono_image_add_stream_data (&assembly->us, "", 1);
5434         } else {
5435                 idx = assembly->us.index ++;
5436         }
5437
5438         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5439
5440         return MONO_TOKEN_STRING | idx;
5441 }
5442
5443 guint32
5444 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5445 {
5446         MonoClass *klass;
5447         guint32 token = 0;
5448         MonoMethodSignature *sig;
5449
5450         mono_error_init (error);
5451
5452         klass = obj->vtable->klass;
5453         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5454                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5455                 MonoMethodSignature *old;
5456                 guint32 sig_token, parent;
5457                 int nargs, i;
5458
5459                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5460
5461                 nargs = mono_array_length (opt_param_types);
5462                 old = mono_method_signature (method);
5463                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5464
5465                 sig->hasthis = old->hasthis;
5466                 sig->explicit_this = old->explicit_this;
5467                 sig->call_convention = old->call_convention;
5468                 sig->generic_param_count = old->generic_param_count;
5469                 sig->param_count = old->param_count + nargs;
5470                 sig->sentinelpos = old->param_count;
5471                 sig->ret = old->ret;
5472
5473                 for (i = 0; i < old->param_count; i++)
5474                         sig->params [i] = old->params [i];
5475
5476                 for (i = 0; i < nargs; i++) {
5477                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5478                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5479                         if (!is_ok (error)) goto fail;
5480                 }
5481
5482                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5483                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5484                 parent >>= MONO_TYPEDEFORREF_BITS;
5485
5486                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5487                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5488
5489                 sig_token = method_encode_signature (assembly, sig);
5490                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5491         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5492                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5493                 ReflectionMethodBuilder rmb;
5494                 guint32 parent, sig_token;
5495                 int nopt_args, nparams, ngparams, i;
5496
5497                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5498                         goto fail;
5499                 
5500                 rmb.opt_types = opt_param_types;
5501                 nopt_args = mono_array_length (opt_param_types);
5502
5503                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5504                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5505                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5506
5507                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5508                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5509                 sig->call_convention = rmb.call_conv;
5510                 sig->generic_param_count = ngparams;
5511                 sig->param_count = nparams + nopt_args;
5512                 sig->sentinelpos = nparams;
5513                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5514                 if (!is_ok (error)) goto fail;
5515
5516                 for (i = 0; i < nparams; i++) {
5517                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5518                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5519                         if (!is_ok (error)) goto fail;
5520                 }
5521
5522                 for (i = 0; i < nopt_args; i++) {
5523                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5524                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5525                         if (!is_ok (error)) goto fail;
5526                 }
5527
5528                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5529                 if (!is_ok (error))
5530                         goto fail;
5531
5532                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5533                 if (!mono_error_ok (error))
5534                         goto fail;
5535                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5536
5537                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5538                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5539
5540                 char *name = mono_string_to_utf8_checked (rmb.name, error);
5541                 if (!is_ok (error)) goto fail;
5542                 token = mono_image_get_varargs_method_token (
5543                         assembly, parent, name, sig_token);
5544                 g_free (name);
5545         } else {
5546                 g_error ("requested method token for %s\n", klass->name);
5547         }
5548
5549         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5550         register_dyn_token (assembly, token, obj);
5551         return token;
5552 fail:
5553         g_assert (!mono_error_ok (error));
5554         return 0;
5555 }
5556
5557 /*
5558  * mono_image_create_token:
5559  * @assembly: a dynamic assembly
5560  * @obj:
5561  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5562  *
5563  * Get a token to insert in the IL code stream for the given MemberInfo.
5564  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5565  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5566  * entry.
5567  */
5568 guint32
5569 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5570                          gboolean create_open_instance, gboolean register_token,
5571                          MonoError *error)
5572 {
5573         MonoClass *klass;
5574         guint32 token = 0;
5575
5576         mono_error_init (error);
5577
5578         klass = obj->vtable->klass;
5579
5580         /* Check for user defined reflection objects */
5581         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5582         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5583                 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5584                 return 0;
5585         }
5586
5587         if (strcmp (klass->name, "MethodBuilder") == 0) {
5588                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5589                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5590
5591                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5592                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5593                 else {
5594                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5595                         if (!mono_error_ok (error))
5596                                 return 0;
5597                 }
5598                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5599         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5600                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5601                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5602
5603                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5604                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5605                 else {
5606                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5607                         if (!mono_error_ok (error))
5608                                 return 0;
5609                 }
5610                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5611         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5612                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5613                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5614                 if (tb->generic_params) {
5615                         token = mono_image_get_generic_field_token (assembly, fb, error);
5616                         return_val_if_nok (error, 0);
5617                 } else {
5618                         if (tb->module->dynamic_image == assembly) {
5619                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5620                         } else {
5621                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5622                         }
5623                 }
5624         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5625                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5626                 if (create_open_instance && tb->generic_params) {
5627                         MonoType *type;
5628                         init_type_builder_generics (obj, error);
5629                         return_val_if_nok (error, 0);
5630                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5631                         return_val_if_nok (error, 0);
5632                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5633                         token = mono_metadata_token_from_dor (token);
5634                 } else if (tb->module->dynamic_image == assembly) {
5635                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5636                 } else {
5637                         MonoType *type;
5638                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5639                         return_val_if_nok (error, 0);
5640                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5641                 }
5642         } else if (strcmp (klass->name, "RuntimeType") == 0) {
5643                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5644                 return_val_if_nok (error, 0);
5645                 MonoClass *mc = mono_class_from_mono_type (type);
5646                 token = mono_metadata_token_from_dor (
5647                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5648         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5649                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5650                 return_val_if_nok (error, 0);
5651                 token = mono_metadata_token_from_dor (
5652                         mono_image_typedef_or_ref (assembly, type));
5653         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5654                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5655                 return_val_if_nok (error, 0);
5656                 token = mono_metadata_token_from_dor (
5657                         mono_image_typedef_or_ref (assembly, type));
5658         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5659                    strcmp (klass->name, "MonoMethod") == 0 ||
5660                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5661                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5662                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5663                 if (m->method->is_inflated) {
5664                         if (create_open_instance)
5665                                 token = mono_image_get_methodspec_token (assembly, m->method);
5666                         else
5667                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5668                 } else if ((m->method->klass->image == &assembly->image) &&
5669                          !m->method->klass->generic_class) {
5670                         static guint32 method_table_idx = 0xffffff;
5671                         if (m->method->klass->wastypebuilder) {
5672                                 /* we use the same token as the one that was assigned
5673                                  * to the Methodbuilder.
5674                                  * FIXME: do the equivalent for Fields.
5675                                  */
5676                                 token = m->method->token;
5677                         } else {
5678                                 /*
5679                                  * Each token should have a unique index, but the indexes are
5680                                  * assigned by managed code, so we don't know about them. An
5681                                  * easy solution is to count backwards...
5682                                  */
5683                                 method_table_idx --;
5684                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5685                         }
5686                 } else {
5687                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5688                 }
5689                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5690         } else if (strcmp (klass->name, "MonoField") == 0) {
5691                 MonoReflectionField *f = (MonoReflectionField *)obj;
5692                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5693                         static guint32 field_table_idx = 0xffffff;
5694                         field_table_idx --;
5695                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5696                 } else {
5697                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5698                 }
5699                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5700         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5701                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5702                 token = mono_image_get_array_token (assembly, m, error);
5703                 return_val_if_nok (error, 0);
5704         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5705                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5706                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5707                 return_val_if_nok (error, 0);
5708         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5709                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5710                 return_val_if_nok (error, 0);
5711                 token = mono_metadata_token_from_dor (
5712                         mono_image_typedef_or_ref (assembly, type));
5713         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5714                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5715                 token = mono_image_get_field_on_inst_token (assembly, f, error);
5716                 return_val_if_nok (error, 0);
5717         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5718                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5719                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5720                 if (!mono_error_ok (error))
5721                         return 0;
5722         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5723                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5724                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5725                 if (!mono_error_ok (error))
5726                         return 0;
5727         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5728                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5729                 return_val_if_nok (error, 0);
5730                 token = mono_metadata_token_from_dor (
5731                                 mono_image_typedef_or_ref (assembly, type));
5732         } else {
5733                 g_error ("requested token for %s\n", klass->name);
5734         }
5735
5736         if (register_token)
5737                 mono_image_register_token (assembly, token, obj);
5738
5739         return token;
5740 }
5741
5742 /*
5743  * mono_image_register_token:
5744  *
5745  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5746  * the Module.ResolveXXXToken () methods to work.
5747  */
5748 void
5749 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5750 {
5751         MonoObject *prev;
5752
5753         dynamic_image_lock (assembly);
5754         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5755         if (prev) {
5756                 /* There could be multiple MethodInfo objects with the same token */
5757                 //g_assert (prev == obj);
5758         } else {
5759                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5760         }
5761         dynamic_image_unlock (assembly);
5762 }
5763
5764 static MonoDynamicImage*
5765 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5766 {
5767         static const guchar entrycode [16] = {0xff, 0x25, 0};
5768         MonoDynamicImage *image;
5769         int i;
5770
5771         const char *version;
5772
5773         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5774                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5775         else
5776                 version = mono_get_runtime_info ()->runtime_version;
5777
5778 #if HAVE_BOEHM_GC
5779         /* The MonoGHashTable's need GC tracking */
5780         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5781 #else
5782         image = g_new0 (MonoDynamicImage, 1);
5783 #endif
5784
5785         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5786         
5787         /*g_print ("created image %p\n", image);*/
5788         /* keep in sync with image.c */
5789         image->image.name = assembly_name;
5790         image->image.assembly_name = image->image.name; /* they may be different */
5791         image->image.module_name = module_name;
5792         image->image.version = g_strdup (version);
5793         image->image.md_version_major = 1;
5794         image->image.md_version_minor = 1;
5795         image->image.dynamic = TRUE;
5796
5797         image->image.references = g_new0 (MonoAssembly*, 1);
5798         image->image.references [0] = NULL;
5799
5800         mono_image_init (&image->image);
5801
5802         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");
5803         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5804         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5805         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5806         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5807         image->handleref = g_hash_table_new (NULL, NULL);
5808         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");
5809         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5810         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");
5811         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");
5812         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5813         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5814         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5815         image->gen_params = g_ptr_array_new ();
5816         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5817
5818         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5819         string_heap_init (&image->sheap);
5820         mono_image_add_stream_data (&image->us, "", 1);
5821         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5822         /* import tables... */
5823         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5824         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5825         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5826         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5827         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5828         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5829         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5830         stream_data_align (&image->code);
5831
5832         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5833
5834         for (i=0; i < MONO_TABLE_NUM; ++i) {
5835                 image->tables [i].next_idx = 1;
5836                 image->tables [i].columns = table_sizes [i];
5837         }
5838
5839         image->image.assembly = (MonoAssembly*)assembly;
5840         image->run = assembly->run;
5841         image->save = assembly->save;
5842         image->pe_kind = 0x1; /* ILOnly */
5843         image->machine = 0x14c; /* I386 */
5844         
5845         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5846
5847         dynamic_images_lock ();
5848
5849         if (!dynamic_images)
5850                 dynamic_images = g_ptr_array_new ();
5851
5852         g_ptr_array_add (dynamic_images, image);
5853
5854         dynamic_images_unlock ();
5855
5856         return image;
5857 }
5858 #endif
5859
5860 static void
5861 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5862 {
5863         g_free (key);
5864 }
5865
5866 static void
5867 release_hashtable (MonoGHashTable **hash)
5868 {
5869         if (*hash) {
5870                 mono_g_hash_table_destroy (*hash);
5871                 *hash = NULL;
5872         }
5873 }
5874
5875 void
5876 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5877 {
5878         release_hashtable (&image->token_fixups);
5879         release_hashtable (&image->handleref_managed);
5880         release_hashtable (&image->tokens);
5881         release_hashtable (&image->remapped_tokens);
5882         release_hashtable (&image->generic_def_objects);
5883         release_hashtable (&image->methodspec);
5884 }
5885
5886 // Free dynamic image pass one: Free resources but not image itself
5887 void
5888 mono_dynamic_image_free (MonoDynamicImage *image)
5889 {
5890         MonoDynamicImage *di = image;
5891         GList *list;
5892         int i;
5893
5894         if (di->methodspec)
5895                 mono_g_hash_table_destroy (di->methodspec);
5896         if (di->typespec)
5897                 g_hash_table_destroy (di->typespec);
5898         if (di->typeref)
5899                 g_hash_table_destroy (di->typeref);
5900         if (di->handleref)
5901                 g_hash_table_destroy (di->handleref);
5902         if (di->handleref_managed)
5903                 mono_g_hash_table_destroy (di->handleref_managed);
5904         if (di->tokens)
5905                 mono_g_hash_table_destroy (di->tokens);
5906         if (di->remapped_tokens)
5907                 mono_g_hash_table_destroy (di->remapped_tokens);
5908         if (di->generic_def_objects)
5909                 mono_g_hash_table_destroy (di->generic_def_objects);
5910         if (di->blob_cache) {
5911                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5912                 g_hash_table_destroy (di->blob_cache);
5913         }
5914         if (di->standalonesig_cache)
5915                 g_hash_table_destroy (di->standalonesig_cache);
5916         for (list = di->array_methods; list; list = list->next) {
5917                 ArrayMethod *am = (ArrayMethod *)list->data;
5918                 g_free (am->sig);
5919                 g_free (am->name);
5920                 g_free (am);
5921         }
5922         g_list_free (di->array_methods);
5923         if (di->gen_params) {
5924                 for (i = 0; i < di->gen_params->len; i++) {
5925                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5926                         mono_gc_deregister_root ((char*) &entry->gparam);
5927                         g_free (entry);
5928                 }
5929                 g_ptr_array_free (di->gen_params, TRUE);
5930         }
5931         if (di->token_fixups)
5932                 mono_g_hash_table_destroy (di->token_fixups);
5933         if (di->method_to_table_idx)
5934                 g_hash_table_destroy (di->method_to_table_idx);
5935         if (di->field_to_table_idx)
5936                 g_hash_table_destroy (di->field_to_table_idx);
5937         if (di->method_aux_hash)
5938                 g_hash_table_destroy (di->method_aux_hash);
5939         if (di->vararg_aux_hash)
5940                 g_hash_table_destroy (di->vararg_aux_hash);
5941         g_free (di->strong_name);
5942         g_free (di->win32_res);
5943         if (di->public_key)
5944                 g_free (di->public_key);
5945
5946         /*g_print ("string heap destroy for image %p\n", di);*/
5947         mono_dynamic_stream_reset (&di->sheap);
5948         mono_dynamic_stream_reset (&di->code);
5949         mono_dynamic_stream_reset (&di->resources);
5950         mono_dynamic_stream_reset (&di->us);
5951         mono_dynamic_stream_reset (&di->blob);
5952         mono_dynamic_stream_reset (&di->tstream);
5953         mono_dynamic_stream_reset (&di->guid);
5954         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5955                 g_free (di->tables [i].values);
5956         }
5957
5958         dynamic_images_lock ();
5959
5960         if (dynamic_images)
5961                 g_ptr_array_remove (dynamic_images, di);
5962
5963         dynamic_images_unlock ();
5964 }
5965
5966 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5967 void
5968 mono_dynamic_image_free_image (MonoDynamicImage *image)
5969 {
5970         /* See create_dynamic_mono_image () */
5971 #if HAVE_BOEHM_GC
5972         /* Allocated using GC_MALLOC */
5973 #else
5974         g_free (image);
5975 #endif
5976 }
5977
5978 #ifndef DISABLE_REFLECTION_EMIT
5979
5980 /*
5981  * mono_image_basic_init:
5982  * @assembly: an assembly builder object
5983  *
5984  * Create the MonoImage that represents the assembly builder and setup some
5985  * of the helper hash table and the basic metadata streams.
5986  */
5987 void
5988 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5989 {
5990         MonoError error;
5991         MonoDynamicAssembly *assembly;
5992         MonoDynamicImage *image;
5993         MonoDomain *domain = mono_object_domain (assemblyb);
5994         
5995         if (assemblyb->dynamic_assembly)
5996                 return;
5997
5998 #if HAVE_BOEHM_GC
5999         /* assembly->assembly.image might be GC allocated */
6000         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
6001 #else
6002         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
6003 #endif
6004
6005         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
6006         
6007         assembly->assembly.ref_count = 1;
6008         assembly->assembly.dynamic = TRUE;
6009         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
6010         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
6011         assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
6012         mono_error_raise_exception (&error); /* FIXME don't raise here */
6013         if (assemblyb->culture) {
6014                 assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
6015                 mono_error_raise_exception (&error); /* FIXME don't raise here */
6016         } else
6017                 assembly->assembly.aname.culture = g_strdup ("");
6018
6019         if (assemblyb->version) {
6020                         char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
6021                         mono_error_raise_exception (&error); /* FIXME don't raise here */
6022                         char **version = g_strsplit (vstr, ".", 4);
6023                         char **parts = version;
6024                         assembly->assembly.aname.major = atoi (*parts++);
6025                         assembly->assembly.aname.minor = atoi (*parts++);
6026                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
6027                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
6028
6029                         g_strfreev (version);
6030                         g_free (vstr);
6031         } else {
6032                         assembly->assembly.aname.major = 0;
6033                         assembly->assembly.aname.minor = 0;
6034                         assembly->assembly.aname.build = 0;
6035                         assembly->assembly.aname.revision = 0;
6036         }
6037
6038         assembly->run = assemblyb->access != 2;
6039         assembly->save = assemblyb->access != 1;
6040         assembly->domain = domain;
6041
6042         char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
6043         mono_error_raise_exception (&error); /* FIXME don't raise here */
6044         image = create_dynamic_mono_image (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
6045         image->initial_image = TRUE;
6046         assembly->assembly.aname.name = image->image.name;
6047         assembly->assembly.image = &image->image;
6048         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
6049                 /* -1 to correct for the trailing NULL byte */
6050                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
6051                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6052                 }
6053                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
6054         }
6055
6056         mono_domain_assemblies_lock (domain);
6057         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6058         mono_domain_assemblies_unlock (domain);
6059
6060         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6061         
6062         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6063         
6064         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6065 }
6066
6067 #endif /* !DISABLE_REFLECTION_EMIT */
6068
6069 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6070
6071 static int
6072 calc_section_size (MonoDynamicImage *assembly)
6073 {
6074         int nsections = 0;
6075
6076         /* alignment constraints */
6077         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6078         g_assert ((assembly->code.index % 4) == 0);
6079         assembly->meta_size += 3;
6080         assembly->meta_size &= ~3;
6081         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6082         g_assert ((assembly->resources.index % 4) == 0);
6083
6084         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6085         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6086         nsections++;
6087
6088         if (assembly->win32_res) {
6089                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6090
6091                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6092                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6093                 nsections++;
6094         }
6095
6096         assembly->sections [MONO_SECTION_RELOC].size = 12;
6097         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6098         nsections++;
6099
6100         return nsections;
6101 }
6102
6103 typedef struct {
6104         guint32 id;
6105         guint32 offset;
6106         GSList *children;
6107         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6108 } ResTreeNode;
6109
6110 static int
6111 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6112 {
6113         ResTreeNode *t1 = (ResTreeNode*)a;
6114         ResTreeNode *t2 = (ResTreeNode*)b;
6115
6116         return t1->id - t2->id;
6117 }
6118
6119 /*
6120  * resource_tree_create:
6121  *
6122  *  Organize the resources into a resource tree.
6123  */
6124 static ResTreeNode *
6125 resource_tree_create (MonoArray *win32_resources)
6126 {
6127         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6128         GSList *l;
6129         int i;
6130
6131         tree = g_new0 (ResTreeNode, 1);
6132         
6133         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6134                 MonoReflectionWin32Resource *win32_res =
6135                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6136
6137                 /* Create node */
6138
6139                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6140                 lang_node = g_new0 (ResTreeNode, 1);
6141                 lang_node->id = win32_res->lang_id;
6142                 lang_node->win32_res = win32_res;
6143
6144                 /* Create type node if neccesary */
6145                 type_node = NULL;
6146                 for (l = tree->children; l; l = l->next)
6147                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6148                                 type_node = (ResTreeNode*)l->data;
6149                                 break;
6150                         }
6151
6152                 if (!type_node) {
6153                         type_node = g_new0 (ResTreeNode, 1);
6154                         type_node->id = win32_res->res_type;
6155
6156                         /* 
6157                          * The resource types have to be sorted otherwise
6158                          * Windows Explorer can't display the version information.
6159                          */
6160                         tree->children = g_slist_insert_sorted (tree->children, 
6161                                 type_node, resource_tree_compare_by_id);
6162                 }
6163
6164                 /* Create res node if neccesary */
6165                 res_node = NULL;
6166                 for (l = type_node->children; l; l = l->next)
6167                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6168                                 res_node = (ResTreeNode*)l->data;
6169                                 break;
6170                         }
6171
6172                 if (!res_node) {
6173                         res_node = g_new0 (ResTreeNode, 1);
6174                         res_node->id = win32_res->res_id;
6175                         type_node->children = g_slist_append (type_node->children, res_node);
6176                 }
6177
6178                 res_node->children = g_slist_append (res_node->children, lang_node);
6179         }
6180
6181         return tree;
6182 }
6183
6184 /*
6185  * resource_tree_encode:
6186  * 
6187  *   Encode the resource tree into the format used in the PE file.
6188  */
6189 static void
6190 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6191 {
6192         char *entries;
6193         MonoPEResourceDir dir;
6194         MonoPEResourceDirEntry dir_entry;
6195         MonoPEResourceDataEntry data_entry;
6196         GSList *l;
6197         guint32 res_id_entries;
6198
6199         /*
6200          * For the format of the resource directory, see the article
6201          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6202          * Matt Pietrek
6203          */
6204
6205         memset (&dir, 0, sizeof (dir));
6206         memset (&dir_entry, 0, sizeof (dir_entry));
6207         memset (&data_entry, 0, sizeof (data_entry));
6208
6209         g_assert (sizeof (dir) == 16);
6210         g_assert (sizeof (dir_entry) == 8);
6211         g_assert (sizeof (data_entry) == 16);
6212
6213         node->offset = p - begin;
6214
6215         /* IMAGE_RESOURCE_DIRECTORY */
6216         res_id_entries = g_slist_length (node->children);
6217         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6218
6219         memcpy (p, &dir, sizeof (dir));
6220         p += sizeof (dir);
6221
6222         /* Reserve space for entries */
6223         entries = p;
6224         p += sizeof (dir_entry) * res_id_entries;
6225
6226         /* Write children */
6227         for (l = node->children; l; l = l->next) {
6228                 ResTreeNode *child = (ResTreeNode*)l->data;
6229
6230                 if (child->win32_res) {
6231                         guint32 size;
6232
6233                         child->offset = p - begin;
6234
6235                         /* IMAGE_RESOURCE_DATA_ENTRY */
6236                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6237                         size = mono_array_length (child->win32_res->res_data);
6238                         data_entry.rde_size = GUINT32_TO_LE (size);
6239
6240                         memcpy (p, &data_entry, sizeof (data_entry));
6241                         p += sizeof (data_entry);
6242
6243                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6244                         p += size;
6245                 } else {
6246                         resource_tree_encode (child, begin, p, &p);
6247                 }
6248         }
6249
6250         /* IMAGE_RESOURCE_ENTRY */
6251         for (l = node->children; l; l = l->next) {
6252                 ResTreeNode *child = (ResTreeNode*)l->data;
6253
6254                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6255                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6256
6257                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6258                 entries += sizeof (dir_entry);
6259         }
6260
6261         *endbuf = p;
6262 }
6263
6264 static void
6265 resource_tree_free (ResTreeNode * node)
6266 {
6267         GSList * list;
6268         for (list = node->children; list; list = list->next)
6269                 resource_tree_free ((ResTreeNode*)list->data);
6270         g_slist_free(node->children);
6271         g_free (node);
6272 }
6273
6274 static void
6275 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6276 {
6277         char *buf;
6278         char *p;
6279         guint32 size, i;
6280         MonoReflectionWin32Resource *win32_res;
6281         ResTreeNode *tree;
6282
6283         if (!assemblyb->win32_resources)
6284                 return;
6285
6286         /*
6287          * Resources are stored in a three level tree inside the PE file.
6288          * - level one contains a node for each type of resource
6289          * - level two contains a node for each resource
6290          * - level three contains a node for each instance of a resource for a
6291          *   specific language.
6292          */
6293
6294         tree = resource_tree_create (assemblyb->win32_resources);
6295
6296         /* Estimate the size of the encoded tree */
6297         size = 0;
6298         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6299                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6300                 size += mono_array_length (win32_res->res_data);
6301         }
6302         /* Directory structure */
6303         size += mono_array_length (assemblyb->win32_resources) * 256;
6304         p = buf = (char *)g_malloc (size);
6305
6306         resource_tree_encode (tree, p, p, &p);
6307
6308         g_assert (p - buf <= size);
6309
6310         assembly->win32_res = (char *)g_malloc (p - buf);
6311         assembly->win32_res_size = p - buf;
6312         memcpy (assembly->win32_res, buf, p - buf);
6313
6314         g_free (buf);
6315         resource_tree_free (tree);
6316 }
6317
6318 static void
6319 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6320 {
6321         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6322         int i;
6323
6324         p += sizeof (MonoPEResourceDir);
6325         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6326                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6327                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6328                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6329                         fixup_resource_directory (res_section, child, rva);
6330                 } else {
6331                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6332                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6333                 }
6334
6335                 p += sizeof (MonoPEResourceDirEntry);
6336         }
6337 }
6338
6339 static void
6340 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6341 {
6342         guint32 dummy;
6343         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6344                 g_error ("WriteFile returned %d\n", GetLastError ());
6345 }
6346
6347 /*
6348  * mono_image_create_pefile:
6349  * @mb: a module builder object
6350  * 
6351  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6352  * assembly->pefile where it can be easily retrieved later in chunks.
6353  */
6354 gboolean
6355 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6356 {
6357         MonoMSDOSHeader *msdos;
6358         MonoDotNetHeader *header;
6359         MonoSectionTable *section;
6360         MonoCLIHeader *cli_header;
6361         guint32 size, image_size, virtual_base, text_offset;
6362         guint32 header_start, section_start, file_offset, virtual_offset;
6363         MonoDynamicImage *assembly;
6364         MonoReflectionAssemblyBuilder *assemblyb;
6365         MonoDynamicStream pefile_stream = {0};
6366         MonoDynamicStream *pefile = &pefile_stream;
6367         int i, nsections;
6368         guint32 *rva, value;
6369         guchar *p;
6370         static const unsigned char msheader[] = {
6371                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6372                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6373                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6374                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6375                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6376                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6377                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6378                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6379         };
6380
6381         mono_error_init (error);
6382
6383         assemblyb = mb->assemblyb;
6384
6385         mono_image_basic_init (assemblyb);
6386         assembly = mb->dynamic_image;
6387
6388         assembly->pe_kind = assemblyb->pe_kind;
6389         assembly->machine = assemblyb->machine;
6390         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6391         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6392         
6393         if (!mono_image_build_metadata (mb, error))
6394                 return FALSE;
6395         
6396
6397         if (mb->is_main && assemblyb->resources) {
6398                 int len = mono_array_length (assemblyb->resources);
6399                 for (i = 0; i < len; ++i)
6400                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6401         }
6402
6403         if (mb->resources) {
6404                 int len = mono_array_length (mb->resources);
6405                 for (i = 0; i < len; ++i)
6406                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6407         }
6408
6409         if (!build_compressed_metadata (assembly, error))
6410                 return FALSE;
6411
6412         if (mb->is_main)
6413                 assembly_add_win32_resources (assembly, assemblyb);
6414
6415         nsections = calc_section_size (assembly);
6416         
6417         /* The DOS header and stub */
6418         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6419         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6420
6421         /* the dotnet header */
6422         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6423
6424         /* the section tables */
6425         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6426
6427         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6428         virtual_offset = VIRT_ALIGN;
6429         image_size = 0;
6430
6431         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6432                 if (!assembly->sections [i].size)
6433                         continue;
6434                 /* align offsets */
6435                 file_offset += FILE_ALIGN - 1;
6436                 file_offset &= ~(FILE_ALIGN - 1);
6437                 virtual_offset += VIRT_ALIGN - 1;
6438                 virtual_offset &= ~(VIRT_ALIGN - 1);
6439
6440                 assembly->sections [i].offset = file_offset;
6441                 assembly->sections [i].rva = virtual_offset;
6442
6443                 file_offset += assembly->sections [i].size;
6444                 virtual_offset += assembly->sections [i].size;
6445                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6446         }
6447
6448         file_offset += FILE_ALIGN - 1;
6449         file_offset &= ~(FILE_ALIGN - 1);
6450
6451         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6452
6453         /* back-patch info */
6454         msdos = (MonoMSDOSHeader*)pefile->data;
6455         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6456
6457         header = (MonoDotNetHeader*)(pefile->data + header_start);
6458         header->pesig [0] = 'P';
6459         header->pesig [1] = 'E';
6460         
6461         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6462         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6463         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6464         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6465         if (assemblyb->pekind == 1) {
6466                 /* it's a dll */
6467                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6468         } else {
6469                 /* it's an exe */
6470                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6471         }
6472
6473         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6474
6475         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6476         header->pe.pe_major = 6;
6477         header->pe.pe_minor = 0;
6478         size = assembly->sections [MONO_SECTION_TEXT].size;
6479         size += FILE_ALIGN - 1;
6480         size &= ~(FILE_ALIGN - 1);
6481         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6482         size = assembly->sections [MONO_SECTION_RSRC].size;
6483         size += FILE_ALIGN - 1;
6484         size &= ~(FILE_ALIGN - 1);
6485         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6486         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6487         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6488         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6489         /* pe_rva_entry_point always at the beginning of the text section */
6490         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6491
6492         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6493         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6494         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6495         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6496         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6497         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6498         size = section_start;
6499         size += FILE_ALIGN - 1;
6500         size &= ~(FILE_ALIGN - 1);
6501         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6502         size = image_size;
6503         size += VIRT_ALIGN - 1;
6504         size &= ~(VIRT_ALIGN - 1);
6505         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6506
6507         /*
6508         // Translate the PEFileKind value to the value expected by the Windows loader
6509         */
6510         {
6511                 short kind;
6512
6513                 /*
6514                 // PEFileKinds.Dll == 1
6515                 // PEFileKinds.ConsoleApplication == 2
6516                 // PEFileKinds.WindowApplication == 3
6517                 //
6518                 // need to get:
6519                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6520                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6521                 */
6522                 if (assemblyb->pekind == 3)
6523                         kind = 2;
6524                 else
6525                         kind = 3;
6526                 
6527                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6528         }    
6529         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6530         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6531         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6532         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6533         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6534         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6535
6536         /* fill data directory entries */
6537
6538         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6539         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6540
6541         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6542         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6543
6544         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6545         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6546         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6547         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6548         /* patch entrypoint name */
6549         if (assemblyb->pekind == 1)
6550                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6551         else
6552                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6553         /* patch imported function RVA name */
6554         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6555         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6556
6557         /* the import table */
6558         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6559         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6560         /* patch imported dll RVA name and other entries in the dir */
6561         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6562         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6563         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6564         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6565         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6566         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6567
6568         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6569         value = (assembly->text_rva + assembly->imp_names_offset);
6570         *p++ = (value) & 0xff;
6571         *p++ = (value >> 8) & (0xff);
6572         *p++ = (value >> 16) & (0xff);
6573         *p++ = (value >> 24) & (0xff);
6574
6575         /* the CLI header info */
6576         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6577         cli_header->ch_size = GUINT32_FROM_LE (72);
6578         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6579         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6580         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6581         if (assemblyb->entry_point) {
6582                 guint32 table_idx = 0;
6583                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6584                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6585                         table_idx = methodb->table_idx;
6586                 } else {
6587                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6588                 }
6589                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6590         } else {
6591                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6592         }
6593         /* The embedded managed resources */
6594         text_offset = assembly->text_rva + assembly->code.index;
6595         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6596         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6597         text_offset += assembly->resources.index;
6598         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6599         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6600         text_offset += assembly->meta_size;
6601         if (assembly->strong_name_size) {
6602                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6603                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6604                 text_offset += assembly->strong_name_size;
6605         }
6606
6607         /* write the section tables and section content */
6608         section = (MonoSectionTable*)(pefile->data + section_start);
6609         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6610                 static const char section_names [][7] = {
6611                         ".text", ".rsrc", ".reloc"
6612                 };
6613                 if (!assembly->sections [i].size)
6614                         continue;
6615                 strcpy (section->st_name, section_names [i]);
6616                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6617                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6618                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6619                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6620                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6621                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6622                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6623                 section ++;
6624         }
6625         
6626         checked_write_file (file, pefile->data, pefile->index);
6627         
6628         mono_dynamic_stream_reset (pefile);
6629         
6630         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6631                 if (!assembly->sections [i].size)
6632                         continue;
6633                 
6634                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6635                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6636                 
6637                 switch (i) {
6638                 case MONO_SECTION_TEXT:
6639                         /* patch entry point */
6640                         p = (guchar*)(assembly->code.data + 2);
6641                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6642                         *p++ = (value) & 0xff;
6643                         *p++ = (value >> 8) & 0xff;
6644                         *p++ = (value >> 16) & 0xff;
6645                         *p++ = (value >> 24) & 0xff;
6646                 
6647                         checked_write_file (file, assembly->code.data, assembly->code.index);
6648                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6649                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6650                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6651                                 
6652
6653                         g_free (assembly->image.raw_metadata);
6654                         break;
6655                 case MONO_SECTION_RELOC: {
6656                         struct {
6657                                 guint32 page_rva;
6658                                 guint32 block_size;
6659                                 guint16 type_and_offset;
6660                                 guint16 term;
6661                         } reloc;
6662                         
6663                         g_assert (sizeof (reloc) == 12);
6664                         
6665                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6666                         reloc.block_size = GUINT32_FROM_LE (12);
6667                         
6668                         /* 
6669                          * the entrypoint is always at the start of the text section 
6670                          * 3 is IMAGE_REL_BASED_HIGHLOW
6671                          * 2 is patch_size_rva - text_rva
6672                          */
6673                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6674                         reloc.term = 0;
6675                         
6676                         checked_write_file (file, &reloc, sizeof (reloc));
6677                         
6678                         break;
6679                 }
6680                 case MONO_SECTION_RSRC:
6681                         if (assembly->win32_res) {
6682
6683                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6684                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6685                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6686                         }
6687                         break;
6688                 default:
6689                         g_assert_not_reached ();
6690                 }
6691         }
6692         
6693         /* check that the file is properly padded */
6694         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6695                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6696         if (! SetEndOfFile (file))
6697                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6698         
6699         mono_dynamic_stream_reset (&assembly->code);
6700         mono_dynamic_stream_reset (&assembly->us);
6701         mono_dynamic_stream_reset (&assembly->blob);
6702         mono_dynamic_stream_reset (&assembly->guid);
6703         mono_dynamic_stream_reset (&assembly->sheap);
6704
6705         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6706         g_hash_table_destroy (assembly->blob_cache);
6707         assembly->blob_cache = NULL;
6708
6709         return TRUE;
6710 }
6711
6712 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6713
6714 gboolean
6715 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6716 {
6717         g_assert_not_reached ();
6718 }
6719
6720 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6721
6722 #ifndef DISABLE_REFLECTION_EMIT
6723
6724 MonoReflectionModule *
6725 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6726 {
6727         char *name;
6728         MonoImage *image;
6729         MonoImageOpenStatus status;
6730         MonoDynamicAssembly *assembly;
6731         guint32 module_count;
6732         MonoImage **new_modules;
6733         gboolean *new_modules_loaded;
6734         
6735         mono_error_init (error);
6736         
6737         name = mono_string_to_utf8_checked (fileName, error);
6738         return_val_if_nok (error, NULL);
6739
6740         image = mono_image_open (name, &status);
6741         if (!image) {
6742                 if (status == MONO_IMAGE_ERROR_ERRNO)
6743                         mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6744                 else
6745                         mono_error_set_bad_image_name (error, name, NULL);
6746                 g_free (name);
6747                 return NULL;
6748         }
6749
6750         g_free (name);
6751
6752         assembly = ab->dynamic_assembly;
6753         image->assembly = (MonoAssembly*)assembly;
6754
6755         module_count = image->assembly->image->module_count;
6756         new_modules = g_new0 (MonoImage *, module_count + 1);
6757         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6758
6759         if (image->assembly->image->modules)
6760                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6761         if (image->assembly->image->modules_loaded)
6762                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6763         new_modules [module_count] = image;
6764         new_modules_loaded [module_count] = TRUE;
6765         mono_image_addref (image);
6766
6767         g_free (image->assembly->image->modules);
6768         image->assembly->image->modules = new_modules;
6769         image->assembly->image->modules_loaded = new_modules_loaded;
6770         image->assembly->image->module_count ++;
6771
6772         mono_assembly_load_references (image, &status);
6773         if (status) {
6774                 mono_image_close (image);
6775                 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6776                 return NULL;
6777         }
6778
6779         return mono_module_get_object_checked (mono_domain_get (), image, error);
6780 }
6781
6782 #endif /* DISABLE_REFLECTION_EMIT */
6783
6784 /*
6785  * We need to return always the same object for MethodInfo, FieldInfo etc..
6786  * but we need to consider the reflected type.
6787  * type uses a different hash, since it uses custom hash/equal functions.
6788  */
6789
6790 typedef struct {
6791         gpointer item;
6792         MonoClass *refclass;
6793 } ReflectedEntry;
6794
6795 static gboolean
6796 reflected_equal (gconstpointer a, gconstpointer b) {
6797         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6798         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6799
6800         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6801 }
6802
6803 static guint
6804 reflected_hash (gconstpointer a) {
6805         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6806         return mono_aligned_addr_hash (ea->item);
6807 }
6808
6809 #define CHECK_OBJECT(t,p,k)     \
6810         do {    \
6811                 t _obj; \
6812                 ReflectedEntry e;       \
6813                 e.item = (p);   \
6814                 e.refclass = (k);       \
6815                 mono_domain_lock (domain);      \
6816                 if (!domain->refobject_hash)    \
6817                         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");  \
6818                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6819                         mono_domain_unlock (domain);    \
6820                         return _obj;    \
6821                 }       \
6822         mono_domain_unlock (domain); \
6823         } while (0)
6824
6825 #ifdef HAVE_BOEHM_GC
6826 /* ReflectedEntry doesn't need to be GC tracked */
6827 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6828 #define FREE_REFENTRY(entry) g_free ((entry))
6829 #define REFENTRY_REQUIRES_CLEANUP
6830 #else
6831 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6832 /* FIXME: */
6833 #define FREE_REFENTRY(entry)
6834 #endif
6835
6836 #define CACHE_OBJECT(t,p,o,k)   \
6837         do {    \
6838                 t _obj; \
6839         ReflectedEntry pe; \
6840         pe.item = (p); \
6841         pe.refclass = (k); \
6842         mono_domain_lock (domain); \
6843                 if (!domain->refobject_hash)    \
6844                         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");  \
6845         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6846         if (!_obj) { \
6847                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6848                     e->item = (p);      \
6849                     e->refclass = (k);  \
6850                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6851             _obj = o; \
6852         } \
6853                 mono_domain_unlock (domain);    \
6854         return _obj; \
6855         } while (0)
6856
6857 static void
6858 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6859 {
6860         mono_domain_lock (domain);
6861         if (domain->refobject_hash) {
6862         ReflectedEntry pe;
6863                 gpointer orig_pe, orig_value;
6864
6865                 pe.item = o;
6866                 pe.refclass = klass;
6867                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6868                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6869                         FREE_REFENTRY (orig_pe);
6870                 }
6871         }
6872         mono_domain_unlock (domain);
6873 }
6874
6875 #ifdef REFENTRY_REQUIRES_CLEANUP
6876 static void
6877 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6878 {
6879         FREE_REFENTRY (key);
6880 }
6881 #endif
6882
6883 void
6884 mono_reflection_cleanup_domain (MonoDomain *domain)
6885 {
6886         if (domain->refobject_hash) {
6887 /*let's avoid scanning the whole hashtable if not needed*/
6888 #ifdef REFENTRY_REQUIRES_CLEANUP
6889                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6890 #endif
6891                 mono_g_hash_table_destroy (domain->refobject_hash);
6892                 domain->refobject_hash = NULL;
6893         }
6894 }
6895
6896 #ifndef DISABLE_REFLECTION_EMIT
6897 static gpointer
6898 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6899 {
6900         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6901 }
6902
6903 static gpointer
6904 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6905 {
6906         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6907 }
6908
6909 static gboolean
6910 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
6911 {
6912         MonoDynamicImage *image = moduleb->dynamic_image;
6913         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6914         mono_error_init (error);
6915         if (!image) {
6916                 int module_count;
6917                 MonoImage **new_modules;
6918                 MonoImage *ass;
6919                 char *name, *fqname;
6920                 /*
6921                  * FIXME: we already created an image in mono_image_basic_init (), but
6922                  * we don't know which module it belongs to, since that is only 
6923                  * determined at assembly save time.
6924                  */
6925                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6926                 name = mono_string_to_utf8_checked (ab->name, error);
6927                 return_val_if_nok (error, FALSE);
6928                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
6929                 if (!is_ok (error)) {
6930                         g_free (name);
6931                         return FALSE;
6932                 }
6933                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6934
6935                 moduleb->module.image = &image->image;
6936                 moduleb->dynamic_image = image;
6937                 register_module (mono_object_domain (moduleb), moduleb, image);
6938
6939                 /* register the module with the assembly */
6940                 ass = ab->dynamic_assembly->assembly.image;
6941                 module_count = ass->module_count;
6942                 new_modules = g_new0 (MonoImage *, module_count + 1);
6943
6944                 if (ass->modules)
6945                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6946                 new_modules [module_count] = &image->image;
6947                 mono_image_addref (&image->image);
6948
6949                 g_free (ass->modules);
6950                 ass->modules = new_modules;
6951                 ass->module_count ++;
6952         }
6953         return TRUE;
6954 }
6955
6956 void
6957 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6958 {
6959         MonoError error;
6960         (void) image_module_basic_init (moduleb, &error);
6961         mono_error_set_pending_exception (&error);
6962 }
6963
6964 void
6965 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6966 {
6967         MonoDynamicImage *image = moduleb->dynamic_image;
6968
6969         g_assert (type->type);
6970         image->wrappers_type = mono_class_from_mono_type (type->type);
6971 }
6972
6973 #endif
6974
6975 /*
6976  * mono_assembly_get_object:
6977  * @domain: an app domain
6978  * @assembly: an assembly
6979  *
6980  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6981  */
6982 MonoReflectionAssembly*
6983 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6984 {
6985         MonoError error;
6986         MonoReflectionAssembly *result;
6987         result = mono_assembly_get_object_checked (domain, assembly, &error);
6988         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6989         return result;
6990 }
6991 /*
6992  * mono_assembly_get_object_checked:
6993  * @domain: an app domain
6994  * @assembly: an assembly
6995  *
6996  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6997  */
6998 MonoReflectionAssembly*
6999 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
7000 {
7001         MonoReflectionAssembly *res;
7002         
7003         mono_error_init (error);
7004
7005         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
7006         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
7007         if (!res)
7008                 return NULL;
7009         res->assembly = assembly;
7010
7011         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
7012 }
7013
7014
7015
7016 MonoReflectionModule*   
7017 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
7018 {
7019         MonoError error;
7020         MonoReflectionModule *result;
7021         result = mono_module_get_object_checked (domain, image, &error);
7022         mono_error_cleanup (&error);
7023         return result;
7024 }
7025
7026 MonoReflectionModule*
7027 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
7028 {
7029         MonoReflectionModule *res;
7030         char* basename;
7031         
7032         mono_error_init (error);
7033         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
7034         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7035         if (!res)
7036                 return NULL;
7037
7038         res->image = image;
7039         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7040         if (!assm_obj)
7041                 return NULL;
7042         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7043
7044         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
7045         basename = g_path_get_basename (image->name);
7046         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
7047         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
7048         
7049         g_free (basename);
7050
7051         if (image->assembly->image == image) {
7052                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
7053         } else {
7054                 int i;
7055                 res->token = 0;
7056                 if (image->assembly->image->modules) {
7057                         for (i = 0; i < image->assembly->image->module_count; i++) {
7058                                 if (image->assembly->image->modules [i] == image)
7059                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
7060                         }
7061                         g_assert (res->token);
7062                 }
7063         }
7064
7065         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7066 }
7067
7068 MonoReflectionModule*
7069 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7070 {
7071         MonoError error;
7072         MonoReflectionModule *result;
7073         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7074         mono_error_cleanup (&error);
7075         return result;
7076 }
7077
7078 MonoReflectionModule*
7079 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7080 {
7081         MonoReflectionModule *res;
7082         MonoTableInfo *table;
7083         guint32 cols [MONO_FILE_SIZE];
7084         const char *name;
7085         guint32 i, name_idx;
7086         const char *val;
7087         
7088         mono_error_init (error);
7089
7090         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7091         if (!res)
7092                 return NULL;
7093
7094         table = &image->tables [MONO_TABLE_FILE];
7095         g_assert (table_index < table->rows);
7096         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7097
7098         res->image = NULL;
7099         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7100         if (!assm_obj)
7101                 return NULL;
7102         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7103         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7104
7105         /* Check whenever the row has a corresponding row in the moduleref table */
7106         table = &image->tables [MONO_TABLE_MODULEREF];
7107         for (i = 0; i < table->rows; ++i) {
7108                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7109                 val = mono_metadata_string_heap (image, name_idx);
7110                 if (strcmp (val, name) == 0)
7111                         res->image = image->modules [i];
7112         }
7113
7114         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7115         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7116         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7117         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7118         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7119
7120         return res;
7121 }
7122
7123 static gboolean
7124 verify_safe_for_managed_space (MonoType *type)
7125 {
7126         switch (type->type) {
7127 #ifdef DEBUG_HARDER
7128         case MONO_TYPE_ARRAY:
7129                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7130         case MONO_TYPE_PTR:
7131                 return verify_safe_for_managed_space (type->data.type);
7132         case MONO_TYPE_SZARRAY:
7133                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7134         case MONO_TYPE_GENERICINST: {
7135                 MonoGenericInst *inst = type->data.generic_class->inst;
7136                 int i;
7137                 if (!inst->is_open)
7138                         break;
7139                 for (i = 0; i < inst->type_argc; ++i)
7140                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7141                                 return FALSE;
7142                 return TRUE;
7143         }
7144 #endif
7145         case MONO_TYPE_VAR:
7146         case MONO_TYPE_MVAR:
7147                 return TRUE;
7148         default:
7149                 return TRUE;
7150         }
7151 }
7152
7153 static MonoType*
7154 mono_type_normalize (MonoType *type)
7155 {
7156         int i;
7157         MonoGenericClass *gclass;
7158         MonoGenericInst *ginst;
7159         MonoClass *gtd;
7160         MonoGenericContainer *gcontainer;
7161         MonoType **argv = NULL;
7162         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7163
7164         if (type->type != MONO_TYPE_GENERICINST)
7165                 return type;
7166
7167         gclass = type->data.generic_class;
7168         ginst = gclass->context.class_inst;
7169         if (!ginst->is_open)
7170                 return type;
7171
7172         gtd = gclass->container_class;
7173         gcontainer = gtd->generic_container;
7174         argv = g_newa (MonoType*, ginst->type_argc);
7175
7176         for (i = 0; i < ginst->type_argc; ++i) {
7177                 MonoType *t = ginst->type_argv [i], *norm;
7178                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7179                         is_denorm_gtd = FALSE;
7180                 norm = mono_type_normalize (t);
7181                 argv [i] = norm;
7182                 if (norm != t)
7183                         requires_rebind = TRUE;
7184         }
7185
7186         if (is_denorm_gtd)
7187                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7188
7189         if (requires_rebind) {
7190                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7191                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7192         }
7193
7194         return type;
7195 }
7196 /*
7197  * mono_type_get_object:
7198  * @domain: an app domain
7199  * @type: a type
7200  *
7201  * Return an System.MonoType object representing the type @type.
7202  */
7203 MonoReflectionType*
7204 mono_type_get_object (MonoDomain *domain, MonoType *type)
7205 {
7206         MonoError error;
7207         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7208         mono_error_cleanup (&error);
7209
7210         return ret;
7211 }
7212
7213 MonoReflectionType*
7214 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7215 {
7216         MonoType *norm_type;
7217         MonoReflectionType *res;
7218         MonoClass *klass;
7219
7220         mono_error_init (error);
7221
7222         klass = mono_class_from_mono_type (type);
7223
7224         /*we must avoid using @type as it might have come
7225          * from a mono_metadata_type_dup and the caller
7226          * expects that is can be freed.
7227          * Using the right type from 
7228          */
7229         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7230
7231         /* void is very common */
7232         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7233                 return (MonoReflectionType*)domain->typeof_void;
7234
7235         /*
7236          * If the vtable of the given class was already created, we can use
7237          * the MonoType from there and avoid all locking and hash table lookups.
7238          * 
7239          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7240          * that the resulting object is different.   
7241          */
7242         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7243                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7244                 if (vtable && vtable->type)
7245                         return (MonoReflectionType *)vtable->type;
7246         }
7247
7248         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7249         mono_domain_lock (domain);
7250         if (!domain->type_hash)
7251                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7252                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7253         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7254                 mono_domain_unlock (domain);
7255                 mono_loader_unlock ();
7256                 return res;
7257         }
7258
7259         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7260          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7261          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7262          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7263          * artifact of how generics are encoded and should be transparent to managed code so we
7264          * need to weed out this diference when retrieving managed System.Type objects.
7265          */
7266         norm_type = mono_type_normalize (type);
7267         if (norm_type != type) {
7268                 res = mono_type_get_object_checked (domain, norm_type, error);
7269                 if (!mono_error_ok (error))
7270                         return NULL;
7271                 mono_g_hash_table_insert (domain->type_hash, type, res);
7272                 mono_domain_unlock (domain);
7273                 mono_loader_unlock ();
7274                 return res;
7275         }
7276
7277         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7278         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7279                 g_assert (0);
7280
7281         if (!verify_safe_for_managed_space (type)) {
7282                 mono_domain_unlock (domain);
7283                 mono_loader_unlock ();
7284                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7285                 return NULL;
7286         }
7287
7288         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7289                 gboolean is_type_done = TRUE;
7290                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7291                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7292                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7293                 */
7294                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7295                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7296
7297                         if (gparam->owner && gparam->owner->is_method) {
7298                                 MonoMethod *method = gparam->owner->owner.method;
7299                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7300                                         is_type_done = FALSE;
7301                         } else if (gparam->owner && !gparam->owner->is_method) {
7302                                 MonoClass *klass = gparam->owner->owner.klass;
7303                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7304                                         is_type_done = FALSE;
7305                         }
7306                 } 
7307
7308                 /* g_assert_not_reached (); */
7309                 /* should this be considered an error condition? */
7310                 if (is_type_done && !type->byref) {
7311                         mono_domain_unlock (domain);
7312                         mono_loader_unlock ();
7313                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7314                 }
7315         }
7316         /* This is stored in vtables/JITted code so it has to be pinned */
7317         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
7318         if (!mono_error_ok (error))
7319                 return NULL;
7320
7321         res->type = type;
7322         mono_g_hash_table_insert (domain->type_hash, type, res);
7323
7324         if (type->type == MONO_TYPE_VOID)
7325                 domain->typeof_void = (MonoObject*)res;
7326
7327         mono_domain_unlock (domain);
7328         mono_loader_unlock ();
7329         return res;
7330 }
7331
7332 /*
7333  * mono_method_get_object:
7334  * @domain: an app domain
7335  * @method: a method
7336  * @refclass: the reflected type (can be NULL)
7337  *
7338  * Return an System.Reflection.MonoMethod object representing the method @method.
7339  */
7340 MonoReflectionMethod*
7341 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7342 {
7343         MonoError error;
7344         MonoReflectionMethod *ret = NULL;
7345         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7346         mono_error_cleanup (&error);
7347         return ret;
7348 }
7349
7350 /*
7351  * mono_method_get_object_checked:
7352  * @domain: an app domain
7353  * @method: a method
7354  * @refclass: the reflected type (can be NULL)
7355  * @error: set on error.
7356  *
7357  * Return an System.Reflection.MonoMethod object representing the method @method.
7358  * Returns NULL and sets @error on error.
7359  */
7360 MonoReflectionMethod*
7361 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7362 {
7363         /*
7364          * We use the same C representation for methods and constructors, but the type 
7365          * name in C# is different.
7366          */
7367         MonoReflectionType *rt;
7368         MonoClass *klass;
7369         MonoReflectionMethod *ret;
7370
7371         mono_error_init (error);
7372
7373         if (method->is_inflated) {
7374                 MonoReflectionGenericMethod *gret;
7375
7376                 if (!refclass)
7377                         refclass = method->klass;
7378                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7379                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7380                         klass = mono_class_get_mono_generic_cmethod_class ();
7381                 } else {
7382                         klass = mono_class_get_mono_generic_method_class ();
7383                 }
7384                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7385                 if (!mono_error_ok (error))
7386                         goto leave;
7387                 gret->method.method = method;
7388
7389                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7390
7391                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7392                 if (!mono_error_ok (error))
7393                     goto leave;
7394
7395                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7396
7397                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7398         }
7399
7400         if (!refclass)
7401                 refclass = method->klass;
7402
7403         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7404         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7405                 klass = mono_class_get_mono_cmethod_class ();
7406         }
7407         else {
7408                 klass = mono_class_get_mono_method_class ();
7409         }
7410         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7411         if (!mono_error_ok (error))
7412                 goto leave;
7413         ret->method = method;
7414
7415         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7416         if (!mono_error_ok (error))
7417                 goto leave;
7418
7419         MONO_OBJECT_SETREF (ret, reftype, rt);
7420
7421         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7422
7423 leave:
7424         g_assert (!mono_error_ok (error));
7425         return NULL;
7426 }
7427
7428 /*
7429  * mono_method_clear_object:
7430  *
7431  *   Clear the cached reflection objects for the dynamic method METHOD.
7432  */
7433 void
7434 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7435 {
7436         MonoClass *klass;
7437         g_assert (method_is_dynamic (method));
7438
7439         klass = method->klass;
7440         while (klass) {
7441                 clear_cached_object (domain, method, klass);
7442                 klass = klass->parent;
7443         }
7444         /* Added by mono_param_get_objects () */
7445         clear_cached_object (domain, &(method->signature), NULL);
7446         klass = method->klass;
7447         while (klass) {
7448                 clear_cached_object (domain, &(method->signature), klass);
7449                 klass = klass->parent;
7450         }
7451 }
7452
7453 /*
7454  * mono_field_get_object:
7455  * @domain: an app domain
7456  * @klass: a type
7457  * @field: a field
7458  *
7459  * Return an System.Reflection.MonoField object representing the field @field
7460  * in class @klass.
7461  */
7462 MonoReflectionField*
7463 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7464 {
7465         MonoError error;
7466         MonoReflectionField *result;
7467         result = mono_field_get_object_checked (domain, klass, field, &error);
7468         mono_error_cleanup (&error);
7469         return result;
7470 }
7471
7472 /*
7473  * mono_field_get_object_checked:
7474  * @domain: an app domain
7475  * @klass: a type
7476  * @field: a field
7477  * @error: set on error
7478  *
7479  * Return an System.Reflection.MonoField object representing the field @field
7480  * in class @klass. On error, returns NULL and sets @error.
7481  */
7482 MonoReflectionField*
7483 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7484 {
7485         MonoReflectionType *rt;
7486         MonoReflectionField *res;
7487
7488         mono_error_init (error);
7489
7490         CHECK_OBJECT (MonoReflectionField *, field, klass);
7491         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7492         if (!res)
7493                 return NULL;
7494         res->klass = klass;
7495         res->field = field;
7496         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7497
7498         if (is_field_on_inst (field)) {
7499                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7500
7501                 rt = mono_type_get_object_checked (domain, field->type, error);
7502                 if (!mono_error_ok (error))
7503                         return NULL;
7504
7505                 MONO_OBJECT_SETREF (res, type, rt);
7506         } else {
7507                 if (field->type) {
7508                         rt = mono_type_get_object_checked (domain, field->type, error);
7509                         if (!mono_error_ok (error))
7510                                 return NULL;
7511
7512                         MONO_OBJECT_SETREF (res, type, rt);
7513                 }
7514                 res->attrs = mono_field_get_flags (field);
7515         }
7516         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7517 }
7518
7519 /*
7520  * mono_property_get_object:
7521  * @domain: an app domain
7522  * @klass: a type
7523  * @property: a property
7524  *
7525  * Return an System.Reflection.MonoProperty object representing the property @property
7526  * in class @klass.
7527  */
7528 MonoReflectionProperty*
7529 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7530 {
7531         MonoError error;
7532         MonoReflectionProperty *result;
7533         result = mono_property_get_object_checked (domain, klass, property, &error);
7534         mono_error_cleanup (&error);
7535         return result;
7536 }
7537
7538 /**
7539  * mono_property_get_object:
7540  * @domain: an app domain
7541  * @klass: a type
7542  * @property: a property
7543  * @error: set on error
7544  *
7545  * Return an System.Reflection.MonoProperty object representing the property @property
7546  * in class @klass.  On error returns NULL and sets @error.
7547  */
7548 MonoReflectionProperty*
7549 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7550 {
7551         MonoReflectionProperty *res;
7552
7553         mono_error_init (error);
7554
7555         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7556         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7557         if (!res)
7558                 return NULL;
7559         res->klass = klass;
7560         res->property = property;
7561         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7562 }
7563
7564 /*
7565  * mono_event_get_object:
7566  * @domain: an app domain
7567  * @klass: a type
7568  * @event: a event
7569  *
7570  * Return an System.Reflection.MonoEvent object representing the event @event
7571  * in class @klass.
7572  */
7573 MonoReflectionEvent*
7574 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7575 {
7576         MonoError error;
7577         MonoReflectionEvent *result;
7578         result = mono_event_get_object_checked (domain, klass, event, &error);
7579         mono_error_cleanup (&error);
7580         return result;
7581 }
7582
7583 /**
7584  * mono_event_get_object_checked:
7585  * @domain: an app domain
7586  * @klass: a type
7587  * @event: a event
7588  * @error: set on error
7589  *
7590  * Return an System.Reflection.MonoEvent object representing the event @event
7591  * in class @klass. On failure sets @error and returns NULL
7592  */
7593 MonoReflectionEvent*
7594 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7595 {
7596         MonoReflectionEvent *res;
7597         MonoReflectionMonoEvent *mono_event;
7598
7599         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7600         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7601         if (!mono_event)
7602                 return NULL;
7603         mono_event->klass = klass;
7604         mono_event->event = event;
7605         res = (MonoReflectionEvent*)mono_event;
7606         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7607 }
7608
7609 /**
7610  * mono_get_reflection_missing_object:
7611  * @domain: Domain where the object lives
7612  *
7613  * Returns the System.Reflection.Missing.Value singleton object
7614  * (of type System.Reflection.Missing).
7615  *
7616  * Used as the value for ParameterInfo.DefaultValue when Optional
7617  * is present
7618  */
7619 static MonoObject *
7620 mono_get_reflection_missing_object (MonoDomain *domain)
7621 {
7622         MonoError error;
7623         MonoObject *obj;
7624         static MonoClassField *missing_value_field = NULL;
7625         
7626         if (!missing_value_field) {
7627                 MonoClass *missing_klass;
7628                 missing_klass = mono_class_get_missing_class ();
7629                 mono_class_init (missing_klass);
7630                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7631                 g_assert (missing_value_field);
7632         }
7633         obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7634         mono_error_assert_ok (&error);
7635         return obj;
7636 }
7637
7638 static MonoObject*
7639 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7640 {
7641         if (!*dbnull)
7642                 *dbnull = mono_get_dbnull_object (domain);
7643         return *dbnull;
7644 }
7645
7646 static MonoObject*
7647 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7648 {
7649         if (!*reflection_missing)
7650                 *reflection_missing = mono_get_reflection_missing_object (domain);
7651         return *reflection_missing;
7652 }
7653
7654 /*
7655  * mono_param_get_objects:
7656  * @domain: an app domain
7657  * @method: a method
7658  *
7659  * Return an System.Reflection.ParameterInfo array object representing the parameters
7660  * in the method @method.
7661  */
7662 MonoArray*
7663 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7664 {
7665         static MonoClass *System_Reflection_ParameterInfo;
7666         static MonoClass *System_Reflection_ParameterInfo_array;
7667         MonoArray *res = NULL;
7668         MonoReflectionMethod *member = NULL;
7669         MonoReflectionParameter *param = NULL;
7670         char **names = NULL, **blobs = NULL;
7671         guint32 *types = NULL;
7672         MonoType *type = NULL;
7673         MonoObject *dbnull = NULL;
7674         MonoObject *missing = NULL;
7675         MonoMarshalSpec **mspecs = NULL;
7676         MonoMethodSignature *sig = NULL;
7677         MonoVTable *pinfo_vtable;
7678         MonoReflectionType *rt;
7679         int i;
7680
7681         mono_error_init (error);
7682         
7683         if (!System_Reflection_ParameterInfo_array) {
7684                 MonoClass *klass;
7685
7686                 klass = mono_class_get_mono_parameter_info_class ();
7687
7688                 mono_memory_barrier ();
7689                 System_Reflection_ParameterInfo = klass; 
7690
7691         
7692                 klass = mono_array_class_get (klass, 1);
7693                 mono_memory_barrier ();
7694                 System_Reflection_ParameterInfo_array = klass;
7695         }
7696
7697         sig = mono_method_signature_checked (method, error);
7698         if (!mono_error_ok (error))
7699                 goto leave;
7700
7701         if (!sig->param_count) {
7702                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7703                 if (!res)
7704                         goto leave;
7705
7706                 return res;
7707         }
7708
7709         /* Note: the cache is based on the address of the signature into the method
7710          * since we already cache MethodInfos with the method as keys.
7711          */
7712         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7713
7714         member = mono_method_get_object_checked (domain, method, refclass, error);
7715         if (!member)
7716                 goto leave;
7717         names = g_new (char *, sig->param_count);
7718         mono_method_get_param_names (method, (const char **) names);
7719
7720         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7721         mono_method_get_marshal_info (method, mspecs);
7722
7723         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7724         if (!res)
7725                 goto leave;
7726
7727         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7728         for (i = 0; i < sig->param_count; ++i) {
7729                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7730                 if (!param)
7731                         goto leave;
7732
7733                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7734                 if (!rt)
7735                         goto leave;
7736
7737                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7738
7739                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7740
7741                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7742
7743                 param->PositionImpl = i;
7744                 param->AttrsImpl = sig->params [i]->attrs;
7745
7746                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7747                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7748                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7749                         else
7750                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7751                 } else {
7752
7753                         if (!blobs) {
7754                                 blobs = g_new0 (char *, sig->param_count);
7755                                 types = g_new0 (guint32, sig->param_count);
7756                                 get_default_param_value_blobs (method, blobs, types); 
7757                         }
7758
7759                         /* Build MonoType for the type from the Constant Table */
7760                         if (!type)
7761                                 type = g_new0 (MonoType, 1);
7762                         type->type = (MonoTypeEnum)types [i];
7763                         type->data.klass = NULL;
7764                         if (types [i] == MONO_TYPE_CLASS)
7765                                 type->data.klass = mono_defaults.object_class;
7766                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7767                                 /* For enums, types [i] contains the base type */
7768
7769                                         type->type = MONO_TYPE_VALUETYPE;
7770                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7771                         } else
7772                                 type->data.klass = mono_class_from_mono_type (type);
7773
7774                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7775                         if (!is_ok (error))
7776                                 goto leave;
7777                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7778
7779                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7780                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7781                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7782                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7783                                 else
7784                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7785                         }
7786                         
7787                 }
7788
7789                 if (mspecs [i + 1]) {
7790                         MonoReflectionMarshalAsAttribute* mobj;
7791                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7792                         if (!mobj)
7793                                 goto leave;
7794                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7795                 }
7796                 
7797                 mono_array_setref (res, i, param);
7798         }
7799
7800 leave:
7801         g_free (names);
7802         g_free (blobs);
7803         g_free (types);
7804         g_free (type);
7805
7806         if (sig) {
7807                 for (i = sig->param_count; i >= 0; i--) {
7808                         if (mspecs [i])
7809                                 mono_metadata_free_marshal_spec (mspecs [i]);
7810                 }
7811         }
7812         g_free (mspecs);
7813
7814         if (!is_ok (error))
7815                 return NULL;
7816         
7817         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7818 }
7819
7820 MonoArray*
7821 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7822 {
7823         MonoError error;
7824         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7825         mono_error_assert_ok (&error);
7826         return result;
7827 }
7828
7829 /*
7830  * mono_method_body_get_object:
7831  * @domain: an app domain
7832  * @method: a method
7833  *
7834  * Return an System.Reflection.MethodBody object representing the method @method.
7835  */
7836 MonoReflectionMethodBody*
7837 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7838 {
7839         MonoError error;
7840         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7841         mono_error_cleanup (&error);
7842         return result;
7843 }
7844
7845 /**
7846  * mono_method_body_get_object_checked:
7847  * @domain: an app domain
7848  * @method: a method
7849  * @error: set on error
7850  *
7851  * Return an System.Reflection.MethodBody object representing the
7852  * method @method.  On failure, returns NULL and sets @error.
7853  */
7854 MonoReflectionMethodBody*
7855 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7856 {
7857         MonoReflectionMethodBody *ret;
7858         MonoMethodHeader *header;
7859         MonoImage *image;
7860         MonoReflectionType *rt;
7861         guint32 method_rva, local_var_sig_token;
7862         char *ptr;
7863         unsigned char format, flags;
7864         int i;
7865
7866         mono_error_init (error);
7867
7868         /* for compatibility with .net */
7869         if (method_is_dynamic (method)) {
7870                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7871                 return NULL;
7872         }
7873
7874         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7875
7876         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7877                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7878             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7879                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7880             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7881                 return NULL;
7882
7883         image = method->klass->image;
7884         header = mono_method_get_header_checked (method, error);
7885         return_val_if_nok (error, NULL);
7886
7887         if (!image_is_dynamic (image)) {
7888                 /* Obtain local vars signature token */
7889                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7890                 ptr = mono_image_rva_map (image, method_rva);
7891                 flags = *(const unsigned char *) ptr;
7892                 format = flags & METHOD_HEADER_FORMAT_MASK;
7893                 switch (format){
7894                 case METHOD_HEADER_TINY_FORMAT:
7895                         local_var_sig_token = 0;
7896                         break;
7897                 case METHOD_HEADER_FAT_FORMAT:
7898                         ptr += 2;
7899                         ptr += 2;
7900                         ptr += 4;
7901                         local_var_sig_token = read32 (ptr);
7902                         break;
7903                 default:
7904                         g_assert_not_reached ();
7905                 }
7906         } else
7907                 local_var_sig_token = 0; //FIXME
7908
7909         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7910         if (!is_ok (error))
7911                 goto fail;
7912
7913         ret->init_locals = header->init_locals;
7914         ret->max_stack = header->max_stack;
7915         ret->local_var_sig_token = local_var_sig_token;
7916         MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
7917         if (!is_ok (error))
7918                 goto fail;
7919         MONO_OBJECT_SETREF (ret, il, il_arr);
7920         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7921
7922         /* Locals */
7923         MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
7924         if (!is_ok (error))
7925                 goto fail;
7926         MONO_OBJECT_SETREF (ret, locals, locals_arr);
7927         for (i = 0; i < header->num_locals; ++i) {
7928                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7929                 if (!is_ok (error))
7930                         goto fail;
7931
7932                 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7933                 if (!is_ok (error))
7934                         goto fail;
7935
7936                 MONO_OBJECT_SETREF (info, local_type, rt);
7937
7938                 info->is_pinned = header->locals [i]->pinned;
7939                 info->local_index = i;
7940                 mono_array_setref (ret->locals, i, info);
7941         }
7942
7943         /* Exceptions */
7944         MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
7945         if (!is_ok (error))
7946                 goto fail;
7947         MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
7948         for (i = 0; i < header->num_clauses; ++i) {
7949                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7950                 if (!is_ok (error))
7951                         goto fail;
7952                 MonoExceptionClause *clause = &header->clauses [i];
7953
7954                 info->flags = clause->flags;
7955                 info->try_offset = clause->try_offset;
7956                 info->try_length = clause->try_len;
7957                 info->handler_offset = clause->handler_offset;
7958                 info->handler_length = clause->handler_len;
7959                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7960                         info->filter_offset = clause->data.filter_offset;
7961                 else if (clause->data.catch_class) {
7962                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7963                         if (!is_ok (error))
7964                                 goto fail;
7965
7966                         MONO_OBJECT_SETREF (info, catch_type, rt);
7967                 }
7968
7969                 mono_array_setref (ret->clauses, i, info);
7970         }
7971
7972         mono_metadata_free_mh (header);
7973         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7974         return ret;
7975
7976 fail:
7977         mono_metadata_free_mh (header);
7978         return NULL;
7979 }
7980
7981 /**
7982  * mono_get_dbnull_object:
7983  * @domain: Domain where the object lives
7984  *
7985  * Returns the System.DBNull.Value singleton object
7986  *
7987  * Used as the value for ParameterInfo.DefaultValue 
7988  */
7989 MonoObject *
7990 mono_get_dbnull_object (MonoDomain *domain)
7991 {
7992         MonoError error;
7993         MonoObject *obj;
7994         static MonoClassField *dbnull_value_field = NULL;
7995         
7996         if (!dbnull_value_field) {
7997                 MonoClass *dbnull_klass;
7998                 dbnull_klass = mono_class_get_dbnull_class ();
7999                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
8000                 g_assert (dbnull_value_field);
8001         }
8002         obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
8003         mono_error_assert_ok (&error);
8004         return obj;
8005 }
8006
8007 static void
8008 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
8009 {
8010         guint32 param_index, i, lastp, crow = 0;
8011         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
8012         gint32 idx;
8013
8014         MonoClass *klass = method->klass;
8015         MonoImage *image = klass->image;
8016         MonoMethodSignature *methodsig = mono_method_signature (method);
8017
8018         MonoTableInfo *constt;
8019         MonoTableInfo *methodt;
8020         MonoTableInfo *paramt;
8021
8022         if (!methodsig->param_count)
8023                 return;
8024
8025         mono_class_init (klass);
8026
8027         if (image_is_dynamic (klass->image)) {
8028                 MonoReflectionMethodAux *aux;
8029                 if (method->is_inflated)
8030                         method = ((MonoMethodInflated*)method)->declaring;
8031                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8032                 if (aux && aux->param_defaults) {
8033                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
8034                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
8035                 }
8036                 return;
8037         }
8038
8039         methodt = &klass->image->tables [MONO_TABLE_METHOD];
8040         paramt = &klass->image->tables [MONO_TABLE_PARAM];
8041         constt = &image->tables [MONO_TABLE_CONSTANT];
8042
8043         idx = mono_method_get_index (method) - 1;
8044         g_assert (idx != -1);
8045
8046         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
8047         if (idx + 1 < methodt->rows)
8048                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
8049         else
8050                 lastp = paramt->rows + 1;
8051
8052         for (i = param_index; i < lastp; ++i) {
8053                 guint32 paramseq;
8054
8055                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
8056                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
8057
8058                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
8059                         continue;
8060
8061                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
8062                 if (!crow) {
8063                         continue;
8064                 }
8065         
8066                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
8067                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
8068                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8069         }
8070
8071         return;
8072 }
8073
8074 MonoObject *
8075 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8076 {
8077         void *retval;
8078         MonoClass *klass;
8079         MonoObject *object;
8080         MonoType *basetype = type;
8081
8082         mono_error_init (error);
8083
8084         if (!blob)
8085                 return NULL;
8086         
8087         klass = mono_class_from_mono_type (type);
8088         if (klass->valuetype) {
8089                 object = mono_object_new_checked (domain, klass, error);
8090                 return_val_if_nok (error, NULL);
8091                 retval = ((gchar *) object + sizeof (MonoObject));
8092                 if (klass->enumtype)
8093                         basetype = mono_class_enum_basetype (klass);
8094         } else {
8095                 retval = &object;
8096         }
8097                         
8098         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval, error))
8099                 return object;
8100         else
8101                 return NULL;
8102 }
8103
8104 static int
8105 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8106         int found_sep;
8107         char *s;
8108         gboolean quoted = FALSE;
8109
8110         memset (assembly, 0, sizeof (MonoAssemblyName));
8111         assembly->culture = "";
8112         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8113
8114         if (*p == '"') {
8115                 quoted = TRUE;
8116                 p++;
8117         }
8118         assembly->name = p;
8119         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8120                 p++;
8121         if (quoted) {
8122                 if (*p != '"')
8123                         return 1;
8124                 *p = 0;
8125                 p++;
8126         }
8127         if (*p != ',')
8128                 return 1;
8129         *p = 0;
8130         /* Remove trailing whitespace */
8131         s = p - 1;
8132         while (*s && g_ascii_isspace (*s))
8133                 *s-- = 0;
8134         p ++;
8135         while (g_ascii_isspace (*p))
8136                 p++;
8137         while (*p) {
8138                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8139                         p += 8;
8140                         assembly->major = strtoul (p, &s, 10);
8141                         if (s == p || *s != '.')
8142                                 return 1;
8143                         p = ++s;
8144                         assembly->minor = strtoul (p, &s, 10);
8145                         if (s == p || *s != '.')
8146                                 return 1;
8147                         p = ++s;
8148                         assembly->build = strtoul (p, &s, 10);
8149                         if (s == p || *s != '.')
8150                                 return 1;
8151                         p = ++s;
8152                         assembly->revision = strtoul (p, &s, 10);
8153                         if (s == p)
8154                                 return 1;
8155                         p = s;
8156                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8157                         p += 8;
8158                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8159                                 assembly->culture = "";
8160                                 p += 7;
8161                         } else {
8162                                 assembly->culture = p;
8163                                 while (*p && *p != ',') {
8164                                         p++;
8165                                 }
8166                         }
8167                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8168                         p += 15;
8169                         if (strncmp (p, "null", 4) == 0) {
8170                                 p += 4;
8171                         } else {
8172                                 int len;
8173                                 gchar *start = p;
8174                                 while (*p && *p != ',') {
8175                                         p++;
8176                                 }
8177                                 len = (p - start + 1);
8178                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8179                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8180                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8181                         }
8182                 } else {
8183                         while (*p && *p != ',')
8184                                 p++;
8185                 }
8186                 found_sep = 0;
8187                 while (g_ascii_isspace (*p) || *p == ',') {
8188                         *p++ = 0;
8189                         found_sep = 1;
8190                         continue;
8191                 }
8192                 /* failed */
8193                 if (!found_sep)
8194                         return 1;
8195         }
8196
8197         return 0;
8198 }
8199
8200 /*
8201  * mono_reflection_parse_type:
8202  * @name: type name
8203  *
8204  * Parse a type name as accepted by the GetType () method and output the info
8205  * extracted in the info structure.
8206  * the name param will be mangled, so, make a copy before passing it to this function.
8207  * The fields in info will be valid until the memory pointed to by name is valid.
8208  *
8209  * See also mono_type_get_name () below.
8210  *
8211  * Returns: 0 on parse error.
8212  */
8213 static int
8214 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8215                              MonoTypeNameParse *info)
8216 {
8217         char *start, *p, *w, *last_point, *startn;
8218         int in_modifiers = 0;
8219         int isbyref = 0, rank = 0, isptr = 0;
8220
8221         start = p = w = name;
8222
8223         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8224         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8225         info->name = info->name_space = NULL;
8226         info->nested = NULL;
8227         info->modifiers = NULL;
8228         info->type_arguments = NULL;
8229
8230         /* last_point separates the namespace from the name */
8231         last_point = NULL;
8232         /* Skips spaces */
8233         while (*p == ' ') p++, start++, w++, name++;
8234
8235         while (*p) {
8236                 switch (*p) {
8237                 case '+':
8238                         *p = 0; /* NULL terminate the name */
8239                         startn = p + 1;
8240                         info->nested = g_list_append (info->nested, startn);
8241                         /* we have parsed the nesting namespace + name */
8242                         if (info->name)
8243                                 break;
8244                         if (last_point) {
8245                                 info->name_space = start;
8246                                 *last_point = 0;
8247                                 info->name = last_point + 1;
8248                         } else {
8249                                 info->name_space = (char *)"";
8250                                 info->name = start;
8251                         }
8252                         break;
8253                 case '.':
8254                         last_point = p;
8255                         break;
8256                 case '\\':
8257                         ++p;
8258                         break;
8259                 case '&':
8260                 case '*':
8261                 case '[':
8262                 case ',':
8263                 case ']':
8264                         in_modifiers = 1;
8265                         break;
8266                 default:
8267                         break;
8268                 }
8269                 if (in_modifiers)
8270                         break;
8271                 // *w++ = *p++;
8272                 p++;
8273         }
8274         
8275         if (!info->name) {
8276                 if (last_point) {
8277                         info->name_space = start;
8278                         *last_point = 0;
8279                         info->name = last_point + 1;
8280                 } else {
8281                         info->name_space = (char *)"";
8282                         info->name = start;
8283                 }
8284         }
8285         while (*p) {
8286                 switch (*p) {
8287                 case '&':
8288                         if (isbyref) /* only one level allowed by the spec */
8289                                 return 0;
8290                         isbyref = 1;
8291                         isptr = 0;
8292                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8293                         *p++ = 0;
8294                         break;
8295                 case '*':
8296                         if (isbyref) /* pointer to ref not okay */
8297                                 return 0;
8298                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8299                         isptr = 1;
8300                         *p++ = 0;
8301                         break;
8302                 case '[':
8303                         if (isbyref) /* array of ref and generic ref are not okay */
8304                                 return 0;
8305                         //Decide if it's an array of a generic argument list
8306                         *p++ = 0;
8307
8308                         if (!*p) //XXX test
8309                                 return 0;
8310                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8311                                 isptr = 0;
8312                                 rank = 1;
8313                                 while (*p) {
8314                                         if (*p == ']')
8315                                                 break;
8316                                         if (*p == ',')
8317                                                 rank++;
8318                                         else if (*p == '*') /* '*' means unknown lower bound */
8319                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8320                                         else
8321                                                 return 0;
8322                                         ++p;
8323                                 }
8324                                 if (*p++ != ']')
8325                                         return 0;
8326                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8327                         } else {
8328                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8329                                         return 0;
8330                                 isptr = 0;
8331                                 info->type_arguments = g_ptr_array_new ();
8332                                 while (*p) {
8333                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8334                                         gboolean fqname = FALSE;
8335
8336                                         g_ptr_array_add (info->type_arguments, subinfo);
8337
8338                                         while (*p == ' ') p++;
8339                                         if (*p == '[') {
8340                                                 p++;
8341                                                 fqname = TRUE;
8342                                         }
8343
8344                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8345                                                 return 0;
8346
8347                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8348                                         if (fqname && (*p != ']')) {
8349                                                 char *aname;
8350
8351                                                 if (*p != ',')
8352                                                         return 0;
8353                                                 *p++ = 0;
8354
8355                                                 aname = p;
8356                                                 while (*p && (*p != ']'))
8357                                                         p++;
8358
8359                                                 if (*p != ']')
8360                                                         return 0;
8361
8362                                                 *p++ = 0;
8363                                                 while (*aname) {
8364                                                         if (g_ascii_isspace (*aname)) {
8365                                                                 ++aname;
8366                                                                 continue;
8367                                                         }
8368                                                         break;
8369                                                 }
8370                                                 if (!*aname ||
8371                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8372                                                         return 0;
8373                                         } else if (fqname && (*p == ']')) {
8374                                                 *p++ = 0;
8375                                         }
8376                                         if (*p == ']') {
8377                                                 *p++ = 0;
8378                                                 break;
8379                                         } else if (!*p) {
8380                                                 return 0;
8381                                         }
8382                                         *p++ = 0;
8383                                 }
8384                         }
8385                         break;
8386                 case ']':
8387                         if (is_recursed)
8388                                 goto end;
8389                         return 0;
8390                 case ',':
8391                         if (is_recursed)
8392                                 goto end;
8393                         *p++ = 0;
8394                         while (*p) {
8395                                 if (g_ascii_isspace (*p)) {
8396                                         ++p;
8397                                         continue;
8398                                 }
8399                                 break;
8400                         }
8401                         if (!*p)
8402                                 return 0; /* missing assembly name */
8403                         if (!assembly_name_to_aname (&info->assembly, p))
8404                                 return 0;
8405                         break;
8406                 default:
8407                         return 0;
8408                 }
8409                 if (info->assembly.name)
8410                         break;
8411         }
8412         // *w = 0; /* terminate class name */
8413  end:
8414         if (!info->name || !*info->name)
8415                 return 0;
8416         if (endptr)
8417                 *endptr = p;
8418         /* add other consistency checks */
8419         return 1;
8420 }
8421
8422
8423 /**
8424  * mono_identifier_unescape_type_name_chars:
8425  * @identifier: the display name of a mono type
8426  *
8427  * Returns:
8428  *  The name in internal form, that is without escaping backslashes.
8429  *
8430  *  The string is modified in place!
8431  */
8432 char*
8433 mono_identifier_unescape_type_name_chars(char* identifier)
8434 {
8435         char *w, *r;
8436         if (!identifier)
8437                 return NULL;
8438         for (w = r = identifier; *r != 0; r++)
8439         {
8440                 char c = *r;
8441                 if (c == '\\') {
8442                         r++;
8443                         if (*r == 0)
8444                                 break;
8445                         c = *r;
8446                 }
8447                 *w = c;
8448                 w++;
8449         }
8450         if (w != r)
8451                 *w = 0;
8452         return identifier;
8453 }
8454
8455 void
8456 mono_identifier_unescape_info (MonoTypeNameParse* info);
8457
8458 static void
8459 unescape_each_type_argument(void* data, void* user_data)
8460 {
8461         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8462         mono_identifier_unescape_info (info);
8463 }
8464
8465 static void
8466 unescape_each_nested_name (void* data, void* user_data)
8467 {
8468         char* nested_name = (char*) data;
8469         mono_identifier_unescape_type_name_chars(nested_name);
8470 }
8471
8472 /**
8473  * mono_identifier_unescape_info:
8474  *
8475  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8476  *
8477  * Returns: nothing.
8478  *
8479  * Destructively updates the info by unescaping the identifiers that
8480  * comprise the type namespace, name, nested types (if any) and
8481  * generic type arguments (if any).
8482  *
8483  * The resulting info has the names in internal form.
8484  *
8485  */
8486 void
8487 mono_identifier_unescape_info (MonoTypeNameParse *info)
8488 {
8489         if (!info)
8490                 return;
8491         mono_identifier_unescape_type_name_chars(info->name_space);
8492         mono_identifier_unescape_type_name_chars(info->name);
8493         // but don't escape info->assembly
8494         if (info->type_arguments)
8495                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8496         if (info->nested)
8497                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8498 }
8499
8500 int
8501 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8502 {
8503         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8504         if (ok) {
8505                 mono_identifier_unescape_info (info);
8506         }
8507         return ok;
8508 }
8509
8510 static MonoType*
8511 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8512 {
8513         gboolean type_resolve = FALSE;
8514         MonoType *type;
8515         MonoImage *rootimage = image;
8516
8517         mono_error_init (error);
8518
8519         if (info->assembly.name) {
8520                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8521                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8522                         /* 
8523                          * This could happen in the AOT compiler case when the search hook is not
8524                          * installed.
8525                          */
8526                         assembly = image->assembly;
8527                 if (!assembly) {
8528                         /* then we must load the assembly ourselve - see #60439 */
8529                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8530                         if (!assembly)
8531                                 return NULL;
8532                 }
8533                 image = assembly->image;
8534         } else if (!image) {
8535                 image = mono_defaults.corlib;
8536         }
8537
8538         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8539         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8540                 /* ignore the error and try again */
8541                 mono_error_cleanup (error);
8542                 mono_error_init (error);
8543                 image = mono_defaults.corlib;
8544                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8545         }
8546
8547         return type;
8548 }
8549
8550 /**
8551  * mono_reflection_get_type_internal:
8552  *
8553  * Returns: may return NULL on success, sets error on failure.
8554  */
8555 static MonoType*
8556 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8557 {
8558         MonoClass *klass;
8559         GList *mod;
8560         int modval;
8561         gboolean bounded = FALSE;
8562         
8563         mono_error_init (error);
8564         if (!image)
8565                 image = mono_defaults.corlib;
8566
8567         if (!rootimage)
8568                 rootimage = mono_defaults.corlib;
8569
8570         if (ignorecase)
8571                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8572         else
8573                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8574
8575         if (!klass)
8576                 return NULL;
8577
8578         for (mod = info->nested; mod; mod = mod->next) {
8579                 gpointer iter = NULL;
8580                 MonoClass *parent;
8581
8582                 parent = klass;
8583                 mono_class_init (parent);
8584
8585                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8586                         char *lastp;
8587                         char *nested_name, *nested_nspace;
8588                         gboolean match = TRUE;
8589
8590                         lastp = strrchr ((const char *)mod->data, '.');
8591                         if (lastp) {
8592                                 /* Nested classes can have namespaces */
8593                                 int nspace_len;
8594
8595                                 nested_name = g_strdup (lastp + 1);
8596                                 nspace_len = lastp - (char*)mod->data;
8597                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8598                                 memcpy (nested_nspace, mod->data, nspace_len);
8599                                 nested_nspace [nspace_len] = '\0';
8600
8601                         } else {
8602                                 nested_name = (char *)mod->data;
8603                                 nested_nspace = NULL;
8604                         }
8605
8606                         if (nested_nspace) {
8607                                 if (ignorecase) {
8608                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8609                                                 match = FALSE;
8610                                 } else {
8611                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8612                                                 match = FALSE;
8613                                 }
8614                         }
8615                         if (match) {
8616                                 if (ignorecase) {
8617                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8618                                                 match = FALSE;
8619                                 } else {
8620                                         if (strcmp (klass->name, nested_name) != 0)
8621                                                 match = FALSE;
8622                                 }
8623                         }
8624                         if (lastp) {
8625                                 g_free (nested_name);
8626                                 g_free (nested_nspace);
8627                         }
8628                         if (match)
8629                                 break;
8630                 }
8631
8632                 if (!klass)
8633                         break;
8634         }
8635         if (!klass)
8636                 return NULL;
8637
8638         if (info->type_arguments) {
8639                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8640                 MonoReflectionType *the_type;
8641                 MonoType *instance;
8642                 int i;
8643
8644                 for (i = 0; i < info->type_arguments->len; i++) {
8645                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8646
8647                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8648                         if (!type_args [i]) {
8649                                 g_free (type_args);
8650                                 return NULL;
8651                         }
8652                 }
8653
8654                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8655                 if (!the_type)
8656                         return NULL;
8657
8658                 instance = mono_reflection_bind_generic_parameters (
8659                         the_type, info->type_arguments->len, type_args, error);
8660
8661                 g_free (type_args);
8662                 if (!instance)
8663                         return NULL;
8664
8665                 klass = mono_class_from_mono_type (instance);
8666         }
8667
8668         for (mod = info->modifiers; mod; mod = mod->next) {
8669                 modval = GPOINTER_TO_UINT (mod->data);
8670                 if (!modval) { /* byref: must be last modifier */
8671                         return &klass->this_arg;
8672                 } else if (modval == -1) {
8673                         klass = mono_ptr_class_get (&klass->byval_arg);
8674                 } else if (modval == -2) {
8675                         bounded = TRUE;
8676                 } else { /* array rank */
8677                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8678                 }
8679         }
8680
8681         return &klass->byval_arg;
8682 }
8683
8684 /*
8685  * mono_reflection_get_type:
8686  * @image: a metadata context
8687  * @info: type description structure
8688  * @ignorecase: flag for case-insensitive string compares
8689  * @type_resolve: whenever type resolve was already tried
8690  *
8691  * Build a MonoType from the type description in @info.
8692  * 
8693  */
8694
8695 MonoType*
8696 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8697         MonoError error;
8698         MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8699         mono_error_cleanup (&error);
8700         return result;
8701 }
8702
8703 /**
8704  * mono_reflection_get_type_checked:
8705  * @rootimage: the image of the currently active managed caller
8706  * @image: a metadata context
8707  * @info: type description structure
8708  * @ignorecase: flag for case-insensitive string compares
8709  * @type_resolve: whenever type resolve was already tried
8710  * @error: set on error.
8711  *
8712  * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8713  *
8714  */
8715 MonoType*
8716 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8717         mono_error_init (error);
8718         return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
8719 }
8720
8721
8722 static MonoType*
8723 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8724 {
8725         MonoReflectionAssemblyBuilder *abuilder;
8726         MonoType *type;
8727         int i;
8728
8729         mono_error_init (error);
8730         g_assert (assembly_is_dynamic (assembly));
8731         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8732         if (!abuilder)
8733                 return NULL;
8734
8735         /* Enumerate all modules */
8736
8737         type = NULL;
8738         if (abuilder->modules) {
8739                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8740                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8741                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8742                         if (type)
8743                                 break;
8744                         if (!mono_error_ok (error))
8745                                 return NULL;
8746                 }
8747         }
8748
8749         if (!type && abuilder->loaded_modules) {
8750                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8751                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8752                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8753                         if (type)
8754                                 break;
8755                         if (!mono_error_ok (error))
8756                                 return NULL;
8757                 }
8758         }
8759
8760         return type;
8761 }
8762         
8763 MonoType*
8764 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8765 {
8766         MonoType *type;
8767         MonoReflectionAssembly *assembly;
8768         GString *fullName;
8769         GList *mod;
8770
8771         mono_error_init (error);
8772
8773         if (image && image_is_dynamic (image))
8774                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8775         else {
8776                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8777         }
8778         return_val_if_nok (error, NULL);
8779
8780         if (type)
8781                 return type;
8782         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8783                 return NULL;
8784
8785         if (type_resolve) {
8786                 if (*type_resolve) 
8787                         return NULL;
8788                 else
8789                         *type_resolve = TRUE;
8790         }
8791         
8792         /* Reconstruct the type name */
8793         fullName = g_string_new ("");
8794         if (info->name_space && (info->name_space [0] != '\0'))
8795                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8796         else
8797                 g_string_printf (fullName, "%s", info->name);
8798         for (mod = info->nested; mod; mod = mod->next)
8799                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8800
8801         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8802         if (!is_ok (error)) {
8803                 g_string_free (fullName, TRUE);
8804                 return NULL;
8805         }
8806
8807         if (assembly) {
8808                 if (assembly_is_dynamic (assembly->assembly))
8809                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8810                                                                           info, ignorecase, error);
8811                 else
8812                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8813                                                                   info, ignorecase, error);
8814         }
8815         g_string_free (fullName, TRUE);
8816         return_val_if_nok (error, NULL);
8817         return type;
8818 }
8819
8820 void
8821 mono_reflection_free_type_info (MonoTypeNameParse *info)
8822 {
8823         g_list_free (info->modifiers);
8824         g_list_free (info->nested);
8825
8826         if (info->type_arguments) {
8827                 int i;
8828
8829                 for (i = 0; i < info->type_arguments->len; i++) {
8830                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8831
8832                         mono_reflection_free_type_info (subinfo);
8833                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8834                         g_free (subinfo);
8835                 }
8836
8837                 g_ptr_array_free (info->type_arguments, TRUE);
8838         }
8839 }
8840
8841 /*
8842  * mono_reflection_type_from_name:
8843  * @name: type name.
8844  * @image: a metadata context (can be NULL).
8845  *
8846  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8847  * it defaults to get the type from @image or, if @image is NULL or loading
8848  * from it fails, uses corlib.
8849  * 
8850  */
8851 MonoType*
8852 mono_reflection_type_from_name (char *name, MonoImage *image)
8853 {
8854         MonoError error;
8855         MonoType  *result = mono_reflection_type_from_name_checked (name, image, &error);
8856         mono_error_cleanup (&error);
8857         return result;
8858 }
8859
8860 /**
8861  * mono_reflection_type_from_name_checked:
8862  * @name: type name.
8863  * @image: a metadata context (can be NULL).
8864  * @error: set on errror.
8865  *
8866  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8867  * it defaults to get the type from @image or, if @image is NULL or loading
8868  * from it fails, uses corlib.  On failure returns NULL and sets @error.
8869  * 
8870  */
8871 MonoType*
8872 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8873 {
8874         MonoType *type = NULL;
8875         MonoTypeNameParse info;
8876         char *tmp;
8877
8878         mono_error_init (error);
8879         /* Make a copy since parse_type modifies its argument */
8880         tmp = g_strdup (name);
8881         
8882         /*g_print ("requested type %s\n", str);*/
8883         if (mono_reflection_parse_type (tmp, &info)) {
8884                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8885                 if (!is_ok (error)) {
8886                         g_free (tmp);
8887                         mono_reflection_free_type_info (&info);
8888                         return NULL;
8889                 }
8890         }
8891
8892         g_free (tmp);
8893         mono_reflection_free_type_info (&info);
8894         return type;
8895 }
8896
8897 /*
8898  * mono_reflection_get_token:
8899  *
8900  *   Return the metadata token of OBJ which should be an object
8901  * representing a metadata element.
8902  */
8903 guint32
8904 mono_reflection_get_token (MonoObject *obj)
8905 {
8906         MonoError error;
8907         guint32 result = mono_reflection_get_token_checked (obj, &error);
8908         mono_error_assert_ok (&error);
8909         return result;
8910 }
8911
8912 /**
8913  * mono_reflection_get_token_checked:
8914  * @obj: the object
8915  * @error: set on error
8916  *
8917  *   Return the metadata token of @obj which should be an object
8918  * representing a metadata element.  On failure sets @error.
8919  */
8920 guint32
8921 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8922 {
8923         MonoClass *klass;
8924         guint32 token = 0;
8925
8926         mono_error_init (error);
8927
8928         klass = obj->vtable->klass;
8929
8930         if (strcmp (klass->name, "MethodBuilder") == 0) {
8931                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8932
8933                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8934         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8935                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8936
8937                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8938         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8939                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8940
8941                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8942         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8943                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8944                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8945         } else if (strcmp (klass->name, "RuntimeType") == 0) {
8946                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8947                 return_val_if_nok (error, 0);
8948                 MonoClass *mc = mono_class_from_mono_type (type);
8949                 if (!mono_class_init (mc)) {
8950                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8951                         return 0;
8952                 }
8953
8954                 token = mc->type_token;
8955         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8956                    strcmp (klass->name, "MonoMethod") == 0 ||
8957                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8958                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8959                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8960                 if (m->method->is_inflated) {
8961                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8962                         return inflated->declaring->token;
8963                 } else {
8964                         token = m->method->token;
8965                 }
8966         } else if (strcmp (klass->name, "MonoField") == 0) {
8967                 MonoReflectionField *f = (MonoReflectionField*)obj;
8968
8969                 if (is_field_on_inst (f->field)) {
8970                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8971
8972                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8973                                 int field_index = f->field - dgclass->fields;
8974                                 MonoObject *obj;
8975
8976                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8977                                 obj = dgclass->field_objects [field_index];
8978                                 return mono_reflection_get_token_checked (obj, error);
8979                         }
8980                 }
8981                 token = mono_class_get_field_token (f->field);
8982         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8983                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8984
8985                 token = mono_class_get_property_token (p->property);
8986         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8987                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8988
8989                 token = mono_class_get_event_token (p->event);
8990         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8991                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8992                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8993                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8994
8995                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8996         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8997                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8998
8999                 token = m->token;
9000         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
9001                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
9002         } else {
9003                 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
9004                                                 klass->name_space, klass->name);
9005                 return 0;
9006         }
9007
9008         return token;
9009 }
9010
9011 /*
9012  * Load the type with name @n on behalf of image @image.  On failure sets @error and returns NULL.
9013  * The @is_enum flag only affects the error message that's displayed on failure.
9014  */
9015 static MonoType*
9016 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
9017 {
9018         MonoError inner_error;
9019         MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
9020         if (!t) {
9021                 mono_error_set_type_load_name (error, g_strdup(n), NULL,
9022                                                "Could not load %s %s while decoding custom attribute: %s",
9023                                                is_enum ? "enum type": "type",
9024                                                n,
9025                                                mono_error_get_message (&inner_error));
9026                 mono_error_cleanup (&inner_error);
9027                 return NULL;
9028         }
9029         return t;
9030 }
9031
9032 static MonoClass*
9033 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
9034 {
9035         char *n;
9036         MonoType *t;
9037         int slen = mono_metadata_decode_value (p, &p);
9038
9039         mono_error_init (error);
9040
9041         n = (char *)g_memdup (p, slen + 1);
9042         n [slen] = 0;
9043         t = cattr_type_from_name (n, image, TRUE, error);
9044         g_free (n);
9045         return_val_if_nok (error, NULL);
9046         p += slen;
9047         *end = p;
9048         return mono_class_from_mono_type (t);
9049 }
9050
9051 static void*
9052 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
9053 {
9054         int slen, type = t->type;
9055         MonoClass *tklass = t->data.klass;
9056
9057         mono_error_init (error);
9058
9059 handle_enum:
9060         switch (type) {
9061         case MONO_TYPE_U1:
9062         case MONO_TYPE_I1:
9063         case MONO_TYPE_BOOLEAN: {
9064                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
9065                 *bval = *p;
9066                 *end = p + 1;
9067                 return bval;
9068         }
9069         case MONO_TYPE_CHAR:
9070         case MONO_TYPE_U2:
9071         case MONO_TYPE_I2: {
9072                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
9073                 *val = read16 (p);
9074                 *end = p + 2;
9075                 return val;
9076         }
9077 #if SIZEOF_VOID_P == 4
9078         case MONO_TYPE_U:
9079         case MONO_TYPE_I:
9080 #endif
9081         case MONO_TYPE_R4:
9082         case MONO_TYPE_U4:
9083         case MONO_TYPE_I4: {
9084                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9085                 *val = read32 (p);
9086                 *end = p + 4;
9087                 return val;
9088         }
9089 #if SIZEOF_VOID_P == 8
9090         case MONO_TYPE_U: /* error out instead? this should probably not happen */
9091         case MONO_TYPE_I:
9092 #endif
9093         case MONO_TYPE_U8:
9094         case MONO_TYPE_I8: {
9095                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9096                 *val = read64 (p);
9097                 *end = p + 8;
9098                 return val;
9099         }
9100         case MONO_TYPE_R8: {
9101                 double *val = (double *)g_malloc (sizeof (double));
9102                 readr8 (p, val);
9103                 *end = p + 8;
9104                 return val;
9105         }
9106         case MONO_TYPE_VALUETYPE:
9107                 if (t->data.klass->enumtype) {
9108                         type = mono_class_enum_basetype (t->data.klass)->type;
9109                         goto handle_enum;
9110                 } else {
9111                         MonoClass *k =  t->data.klass;
9112                         
9113                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9114                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9115                                 *val = read64 (p);
9116                                 *end = p + 8;
9117                                 return val;
9118                         }
9119                 }
9120                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9121                 break;
9122                 
9123         case MONO_TYPE_STRING:
9124                 if (*p == (char)0xFF) {
9125                         *end = p + 1;
9126                         return NULL;
9127                 }
9128                 slen = mono_metadata_decode_value (p, &p);
9129                 *end = p + slen;
9130                 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
9131         case MONO_TYPE_CLASS: {
9132                 MonoReflectionType *rt;
9133                 char *n;
9134                 MonoType *t;
9135                 if (*p == (char)0xFF) {
9136                         *end = p + 1;
9137                         return NULL;
9138                 }
9139 handle_type:
9140                 slen = mono_metadata_decode_value (p, &p);
9141                 n = (char *)g_memdup (p, slen + 1);
9142                 n [slen] = 0;
9143                 t = cattr_type_from_name (n, image, FALSE, error);
9144                 g_free (n);
9145                 return_val_if_nok (error, NULL);
9146                 *end = p + slen;
9147
9148                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9149                 if (!mono_error_ok (error))
9150                         return NULL;
9151
9152                 return rt;
9153         }
9154         case MONO_TYPE_OBJECT: {
9155                 char subt = *p++;
9156                 MonoObject *obj;
9157                 MonoClass *subc = NULL;
9158                 void *val;
9159
9160                 if (subt == 0x50) {
9161                         goto handle_type;
9162                 } else if (subt == 0x0E) {
9163                         type = MONO_TYPE_STRING;
9164                         goto handle_enum;
9165                 } else if (subt == 0x1D) {
9166                         MonoType simple_type = {{0}};
9167                         int etype = *p;
9168                         p ++;
9169
9170                         type = MONO_TYPE_SZARRAY;
9171                         if (etype == 0x50) {
9172                                 tklass = mono_defaults.systemtype_class;
9173                         } else if (etype == 0x55) {
9174                                 tklass = load_cattr_enum_type (image, p, &p, error);
9175                                 if (!mono_error_ok (error))
9176                                         return NULL;
9177                         } else {
9178                                 if (etype == 0x51)
9179                                         /* See Partition II, Appendix B3 */
9180                                         etype = MONO_TYPE_OBJECT;
9181                                 simple_type.type = (MonoTypeEnum)etype;
9182                                 tklass = mono_class_from_mono_type (&simple_type);
9183                         }
9184                         goto handle_enum;
9185                 } else if (subt == 0x55) {
9186                         char *n;
9187                         MonoType *t;
9188                         slen = mono_metadata_decode_value (p, &p);
9189                         n = (char *)g_memdup (p, slen + 1);
9190                         n [slen] = 0;
9191                         t = cattr_type_from_name (n, image, FALSE, error);
9192                         g_free (n);
9193                         return_val_if_nok (error, NULL);
9194                         p += slen;
9195                         subc = mono_class_from_mono_type (t);
9196                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9197                         MonoType simple_type = {{0}};
9198                         simple_type.type = (MonoTypeEnum)subt;
9199                         subc = mono_class_from_mono_type (&simple_type);
9200                 } else {
9201                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9202                 }
9203                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9204                 obj = NULL;
9205                 if (mono_error_ok (error)) {
9206                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
9207                         g_assert (!subc->has_references);
9208                         if (mono_error_ok (error))
9209                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9210                 }
9211
9212                 g_free (val);
9213                 return obj;
9214         }
9215         case MONO_TYPE_SZARRAY: {
9216                 MonoArray *arr;
9217                 guint32 i, alen, basetype;
9218                 alen = read32 (p);
9219                 p += 4;
9220                 if (alen == 0xffffffff) {
9221                         *end = p;
9222                         return NULL;
9223                 }
9224                 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
9225                 return_val_if_nok (error, NULL);
9226                 basetype = tklass->byval_arg.type;
9227                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9228                         basetype = mono_class_enum_basetype (tklass)->type;
9229                 switch (basetype)
9230                 {
9231                         case MONO_TYPE_U1:
9232                         case MONO_TYPE_I1:
9233                         case MONO_TYPE_BOOLEAN:
9234                                 for (i = 0; i < alen; i++) {
9235                                         MonoBoolean val = *p++;
9236                                         mono_array_set (arr, MonoBoolean, i, val);
9237                                 }
9238                                 break;
9239                         case MONO_TYPE_CHAR:
9240                         case MONO_TYPE_U2:
9241                         case MONO_TYPE_I2:
9242                                 for (i = 0; i < alen; i++) {
9243                                         guint16 val = read16 (p);
9244                                         mono_array_set (arr, guint16, i, val);
9245                                         p += 2;
9246                                 }
9247                                 break;
9248                         case MONO_TYPE_R4:
9249                         case MONO_TYPE_U4:
9250                         case MONO_TYPE_I4:
9251                                 for (i = 0; i < alen; i++) {
9252                                         guint32 val = read32 (p);
9253                                         mono_array_set (arr, guint32, i, val);
9254                                         p += 4;
9255                                 }
9256                                 break;
9257                         case MONO_TYPE_R8:
9258                                 for (i = 0; i < alen; i++) {
9259                                         double val;
9260                                         readr8 (p, &val);
9261                                         mono_array_set (arr, double, i, val);
9262                                         p += 8;
9263                                 }
9264                                 break;
9265                         case MONO_TYPE_U8:
9266                         case MONO_TYPE_I8:
9267                                 for (i = 0; i < alen; i++) {
9268                                         guint64 val = read64 (p);
9269                                         mono_array_set (arr, guint64, i, val);
9270                                         p += 8;
9271                                 }
9272                                 break;
9273                         case MONO_TYPE_CLASS:
9274                         case MONO_TYPE_OBJECT:
9275                         case MONO_TYPE_STRING:
9276                         case MONO_TYPE_SZARRAY:
9277                                 for (i = 0; i < alen; i++) {
9278                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9279                                         if (!mono_error_ok (error))
9280                                                 return NULL;
9281                                         mono_array_setref (arr, i, item);
9282                                 }
9283                                 break;
9284                         default:
9285                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9286                 }
9287                 *end=p;
9288                 return arr;
9289         }
9290         default:
9291                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9292         }
9293         return NULL;
9294 }
9295
9296 static MonoObject*
9297 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9298 {
9299         mono_error_init (error);
9300
9301         gboolean is_ref = type_is_reference (t);
9302
9303         void *val = load_cattr_value (image, t, p, end, error);
9304         if (!is_ok (error)) {
9305                 if (is_ref)
9306                         g_free (val);
9307                 return NULL;
9308         }
9309
9310         if (is_ref)
9311                 return (MonoObject*)val;
9312
9313         MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9314         g_free (val);
9315         return boxed;
9316 }
9317
9318 static MonoObject*
9319 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9320 {
9321         static MonoMethod *ctor;
9322         MonoObject *retval;
9323         void *params [2], *unboxed;
9324
9325         mono_error_init (error);
9326
9327         if (!ctor)
9328                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9329         
9330         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9331         return_val_if_nok (error, NULL);
9332
9333         params [1] = val;
9334         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9335         return_val_if_nok (error, NULL);
9336         unboxed = mono_object_unbox (retval);
9337
9338         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9339         return_val_if_nok (error, NULL);
9340
9341         return retval;
9342 }
9343
9344 static MonoObject*
9345 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9346 {
9347         static MonoMethod *ctor;
9348         MonoObject *retval;
9349         void *unboxed, *params [2];
9350
9351         mono_error_init (error);
9352
9353         if (!ctor)
9354                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9355
9356         params [0] = minfo;
9357         params [1] = typedarg;
9358         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9359         return_val_if_nok (error, NULL);
9360
9361         unboxed = mono_object_unbox (retval);
9362
9363         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9364         return_val_if_nok (error, NULL);
9365
9366         return retval;
9367 }
9368
9369 static gboolean
9370 type_is_reference (MonoType *type)
9371 {
9372         switch (type->type) {
9373         case MONO_TYPE_BOOLEAN:
9374         case MONO_TYPE_CHAR:
9375         case MONO_TYPE_U:
9376         case MONO_TYPE_I:
9377         case MONO_TYPE_U1:
9378         case MONO_TYPE_I1:
9379         case MONO_TYPE_U2:
9380         case MONO_TYPE_I2:
9381         case MONO_TYPE_U4:
9382         case MONO_TYPE_I4:
9383         case MONO_TYPE_U8:
9384         case MONO_TYPE_I8:
9385         case MONO_TYPE_R8:
9386         case MONO_TYPE_R4:
9387         case MONO_TYPE_VALUETYPE:
9388                 return FALSE;
9389         default:
9390                 return TRUE;
9391         }
9392 }
9393
9394 static void
9395 free_param_data (MonoMethodSignature *sig, void **params) {
9396         int i;
9397         for (i = 0; i < sig->param_count; ++i) {
9398                 if (!type_is_reference (sig->params [i]))
9399                         g_free (params [i]);
9400         }
9401 }
9402
9403 /*
9404  * Find the field index in the metadata FieldDef table.
9405  */
9406 static guint32
9407 find_field_index (MonoClass *klass, MonoClassField *field) {
9408         int i;
9409
9410         for (i = 0; i < klass->field.count; ++i) {
9411                 if (field == &klass->fields [i])
9412                         return klass->field.first + 1 + i;
9413         }
9414         return 0;
9415 }
9416
9417 /*
9418  * Find the property index in the metadata Property table.
9419  */
9420 static guint32
9421 find_property_index (MonoClass *klass, MonoProperty *property) {
9422         int i;
9423
9424         for (i = 0; i < klass->ext->property.count; ++i) {
9425                 if (property == &klass->ext->properties [i])
9426                         return klass->ext->property.first + 1 + i;
9427         }
9428         return 0;
9429 }
9430
9431 /*
9432  * Find the event index in the metadata Event table.
9433  */
9434 static guint32
9435 find_event_index (MonoClass *klass, MonoEvent *event) {
9436         int i;
9437
9438         for (i = 0; i < klass->ext->event.count; ++i) {
9439                 if (event == &klass->ext->events [i])
9440                         return klass->ext->event.first + 1 + i;
9441         }
9442         return 0;
9443 }
9444
9445 static MonoObject*
9446 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9447 {
9448         const char *p = (const char*)data;
9449         const char *named;
9450         guint32 i, j, num_named;
9451         MonoObject *attr;
9452         void *params_buf [32];
9453         void **params = NULL;
9454         MonoMethodSignature *sig;
9455
9456         mono_error_init (error);
9457
9458         mono_class_init (method->klass);
9459
9460         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9461                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9462                 return NULL;
9463         }
9464
9465         if (len == 0) {
9466                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9467                 if (!mono_error_ok (error)) return NULL;
9468
9469                 mono_runtime_invoke_checked (method, attr, NULL, error);
9470                 if (!mono_error_ok (error))
9471                         return NULL;
9472
9473                 return attr;
9474         }
9475
9476         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9477                 return NULL;
9478
9479         /*g_print ("got attr %s\n", method->klass->name);*/
9480
9481         sig = mono_method_signature (method);
9482         if (sig->param_count < 32) {
9483                 params = params_buf;
9484                 memset (params, 0, sizeof (void*) * sig->param_count);
9485         } else {
9486                 /* Allocate using GC so it gets GC tracking */
9487                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9488         }
9489
9490         /* skip prolog */
9491         p += 2;
9492         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9493                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9494                 if (!mono_error_ok (error))
9495                         goto fail;
9496         }
9497
9498         named = p;
9499         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9500         if (!mono_error_ok (error)) goto fail;
9501
9502         MonoObject *exc = NULL;
9503         mono_runtime_try_invoke (method, attr, params, &exc, error);
9504         if (!mono_error_ok (error))
9505                 goto fail;
9506         if (exc) {
9507                 mono_error_set_exception_instance (error, (MonoException*)exc);
9508                 goto fail;
9509         }
9510
9511         num_named = read16 (named);
9512         named += 2;
9513         for (j = 0; j < num_named; j++) {
9514                 gint name_len;
9515                 char *name, named_type, data_type;
9516                 named_type = *named++;
9517                 data_type = *named++; /* type of data */
9518                 if (data_type == MONO_TYPE_SZARRAY)
9519                         data_type = *named++;
9520                 if (data_type == MONO_TYPE_ENUM) {
9521                         gint type_len;
9522                         char *type_name;
9523                         type_len = mono_metadata_decode_blob_size (named, &named);
9524                         type_name = (char *)g_malloc (type_len + 1);
9525                         memcpy (type_name, named, type_len);
9526                         type_name [type_len] = 0;
9527                         named += type_len;
9528                         /* FIXME: lookup the type and check type consistency */
9529                         g_free (type_name);
9530                 }
9531                 name_len = mono_metadata_decode_blob_size (named, &named);
9532                 name = (char *)g_malloc (name_len + 1);
9533                 memcpy (name, named, name_len);
9534                 name [name_len] = 0;
9535                 named += name_len;
9536                 if (named_type == 0x53) {
9537                         MonoClassField *field;
9538                         void *val;
9539
9540                         /* how this fail is a blackbox */
9541                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9542                         if (!field) {
9543                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9544                                 g_free (name);
9545                                 goto fail;
9546                         }
9547
9548                         val = load_cattr_value (image, field->type, named, &named, error);
9549                         if (!mono_error_ok (error)) {
9550                                 g_free (name);
9551                                 if (!type_is_reference (field->type))
9552                                         g_free (val);
9553                                 goto fail;
9554                         }
9555
9556                         mono_field_set_value (attr, field, val);
9557                         if (!type_is_reference (field->type))
9558                                 g_free (val);
9559                 } else if (named_type == 0x54) {
9560                         MonoProperty *prop;
9561                         void *pparams [1];
9562                         MonoType *prop_type;
9563
9564                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9565
9566                         if (!prop) {
9567                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9568                                 g_free (name);
9569                                 goto fail;
9570                         }
9571
9572                         if (!prop->set) {
9573                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9574                                 g_free (name);
9575                                 goto fail;
9576                         }
9577
9578                         /* can we have more that 1 arg in a custom attr named property? */
9579                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9580                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9581
9582                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9583                         if (!mono_error_ok (error)) {
9584                                 g_free (name);
9585                                 if (!type_is_reference (prop_type))
9586                                         g_free (pparams [0]);
9587                                 goto fail;
9588                         }
9589
9590
9591                         mono_property_set_value_checked (prop, attr, pparams, error);
9592                         if (!type_is_reference (prop_type))
9593                                 g_free (pparams [0]);
9594                         if (!is_ok (error)) {
9595                                 g_free (name);
9596                                 goto fail;
9597                         }
9598                 }
9599                 g_free (name);
9600         }
9601
9602         free_param_data (method->signature, params);
9603         if (params != params_buf)
9604                 mono_gc_free_fixed (params);
9605
9606         return attr;
9607
9608 fail:
9609         free_param_data (method->signature, params);
9610         if (params != params_buf)
9611                 mono_gc_free_fixed (params);
9612         return NULL;
9613 }
9614         
9615 /*
9616  * mono_reflection_create_custom_attr_data_args:
9617  *
9618  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9619  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9620  * NAMED_ARG_INFO will contain information about the named arguments.
9621  */
9622 void
9623 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)
9624 {
9625         MonoArray *typedargs, *namedargs;
9626         MonoClass *attrklass;
9627         MonoDomain *domain;
9628         const char *p = (const char*)data;
9629         const char *named;
9630         guint32 i, j, num_named;
9631         CattrNamedArg *arginfo = NULL;
9632
9633         *typed_args = NULL;
9634         *named_args = NULL;
9635         *named_arg_info = NULL;
9636
9637         mono_error_init (error);
9638
9639         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9640                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9641                 return;
9642         }
9643
9644         mono_class_init (method->klass);
9645         
9646         domain = mono_domain_get ();
9647
9648         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9649                 return;
9650
9651         typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
9652         return_if_nok (error);
9653
9654         /* skip prolog */
9655         p += 2;
9656         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9657                 MonoObject *obj;
9658
9659                 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9660                 return_if_nok (error);
9661                 mono_array_setref (typedargs, i, obj);
9662         }
9663
9664         named = p;
9665         num_named = read16 (named);
9666         namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
9667         return_if_nok (error);
9668         named += 2;
9669         attrklass = method->klass;
9670
9671         arginfo = g_new0 (CattrNamedArg, num_named);
9672         *named_arg_info = arginfo;
9673
9674         for (j = 0; j < num_named; j++) {
9675                 gint name_len;
9676                 char *name, named_type, data_type;
9677                 named_type = *named++;
9678                 data_type = *named++; /* type of data */
9679                 if (data_type == MONO_TYPE_SZARRAY)
9680                         data_type = *named++;
9681                 if (data_type == MONO_TYPE_ENUM) {
9682                         gint type_len;
9683                         char *type_name;
9684                         type_len = mono_metadata_decode_blob_size (named, &named);
9685                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9686                                 goto fail;
9687
9688                         type_name = (char *)g_malloc (type_len + 1);
9689                         memcpy (type_name, named, type_len);
9690                         type_name [type_len] = 0;
9691                         named += type_len;
9692                         /* FIXME: lookup the type and check type consistency */
9693                         g_free (type_name);
9694                 }
9695                 name_len = mono_metadata_decode_blob_size (named, &named);
9696                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9697                         goto fail;
9698                 name = (char *)g_malloc (name_len + 1);
9699                 memcpy (name, named, name_len);
9700                 name [name_len] = 0;
9701                 named += name_len;
9702                 if (named_type == 0x53) {
9703                         MonoObject *obj;
9704                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9705
9706                         if (!field) {
9707                                 g_free (name);
9708                                 goto fail;
9709                         }
9710
9711                         arginfo [j].type = field->type;
9712                         arginfo [j].field = field;
9713
9714                         obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9715                         if (!is_ok (error)) {
9716                                 g_free (name);
9717                                 return;
9718                         }
9719                         mono_array_setref (namedargs, j, obj);
9720
9721                 } else if (named_type == 0x54) {
9722                         MonoObject *obj;
9723                         MonoType *prop_type;
9724                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9725
9726                         if (!prop || !prop->set) {
9727                                 g_free (name);
9728                                 goto fail;
9729                         }
9730
9731                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9732                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9733
9734                         arginfo [j].type = prop_type;
9735                         arginfo [j].prop = prop;
9736
9737                         obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9738                         if (!is_ok (error)) {
9739                                 g_free (name);
9740                                 return;
9741                         }
9742                         mono_array_setref (namedargs, j, obj);
9743                 }
9744                 g_free (name);
9745         }
9746
9747         *typed_args = typedargs;
9748         *named_args = namedargs;
9749         return;
9750 fail:
9751         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9752         g_free (arginfo);
9753         *named_arg_info = NULL;
9754 }
9755
9756 static gboolean
9757 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
9758 {
9759         MonoDomain *domain;
9760         MonoArray *typedargs, *namedargs;
9761         MonoImage *image;
9762         MonoMethod *method;
9763         CattrNamedArg *arginfo = NULL;
9764         int i;
9765
9766         mono_error_init (error);
9767
9768         *ctor_args = NULL;
9769         *named_args = NULL;
9770
9771         if (len == 0)
9772                 return TRUE;
9773
9774         image = assembly->assembly->image;
9775         method = ref_method->method;
9776         domain = mono_object_domain (ref_method);
9777
9778         if (!mono_class_init (method->klass)) {
9779                 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (method->klass));
9780                 goto leave;
9781         }
9782
9783         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
9784         if (!is_ok (error))
9785                 goto leave;
9786
9787         if (!typedargs || !namedargs)
9788                 goto leave;
9789
9790         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9791                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9792                 MonoObject *typedarg;
9793
9794                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
9795                 if (!is_ok (error))
9796                         goto leave;
9797                 mono_array_setref (typedargs, i, typedarg);
9798         }
9799
9800         for (i = 0; i < mono_array_length (namedargs); ++i) {
9801                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9802                 MonoObject *typedarg, *namedarg, *minfo;
9803
9804                 if (arginfo [i].prop) {
9805                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
9806                         if (!minfo)
9807                                 goto leave;
9808                 } else {
9809                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
9810                         if (!is_ok (error))
9811                                 goto leave;
9812                 }
9813
9814                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
9815                 if (!is_ok (error))
9816                         goto leave;
9817                 namedarg = create_cattr_named_arg (minfo, typedarg, error);
9818                 if (!is_ok (error))
9819                         goto leave;
9820
9821                 mono_array_setref (namedargs, i, namedarg);
9822         }
9823
9824         *ctor_args = typedargs;
9825         *named_args = namedargs;
9826
9827 leave:
9828         g_free (arginfo);
9829         return mono_error_ok (error);
9830 }
9831
9832 void
9833 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9834 {
9835         MonoError error;
9836         (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
9837         mono_error_set_pending_exception (&error);
9838 }
9839
9840 static MonoObject*
9841 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9842 {
9843         static MonoMethod *ctor;
9844
9845         MonoDomain *domain;
9846         MonoObject *attr;
9847         void *params [4];
9848
9849         mono_error_init (error);
9850
9851         g_assert (image->assembly);
9852
9853         if (!ctor)
9854                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9855
9856         domain = mono_domain_get ();
9857         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9858         return_val_if_nok (error, NULL);
9859         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9860         return_val_if_nok (error, NULL);
9861         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9862         return_val_if_nok (error, NULL);
9863         params [2] = (gpointer)&cattr->data;
9864         params [3] = &cattr->data_size;
9865
9866         mono_runtime_invoke_checked (ctor, attr, params, error);
9867         return_val_if_nok (error, NULL);
9868         return attr;
9869 }
9870
9871 static MonoArray*
9872 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9873 {
9874         MonoArray *result;
9875         MonoObject *attr;
9876         int i, n;
9877
9878         mono_error_init (error);
9879
9880         n = 0;
9881         for (i = 0; i < cinfo->num_attrs; ++i) {
9882                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9883                         n ++;
9884         }
9885
9886         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
9887         return_val_if_nok (error, NULL);
9888         n = 0;
9889         for (i = 0; i < cinfo->num_attrs; ++i) {
9890                 if (!cinfo->attrs [i].ctor) {
9891                         /* The cattr type is not finished yet */
9892                         /* We should include the type name but cinfo doesn't contain it */
9893                         mono_error_set_type_load_name (error, NULL, NULL, "");
9894                         return NULL;
9895                 }
9896                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9897                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9898                         if (!mono_error_ok (error))
9899                                 return result;
9900                         mono_array_setref (result, n, attr);
9901                         n ++;
9902                 }
9903         }
9904         return result;
9905 }
9906
9907 MonoArray*
9908 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9909 {
9910         MonoError error;
9911         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9912         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9913
9914         return result;
9915 }
9916
9917 static MonoArray*
9918 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9919 {
9920         MonoArray *result;
9921         MonoObject *attr;
9922         int i;
9923         
9924         mono_error_init (error);
9925         result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
9926         return_val_if_nok (error, NULL);
9927         for (i = 0; i < cinfo->num_attrs; ++i) {
9928                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9929                 return_val_if_nok (error, NULL);
9930                 mono_array_setref (result, i, attr);
9931         }
9932         return result;
9933 }
9934
9935 /**
9936  * mono_custom_attrs_from_index:
9937  *
9938  * Returns: NULL if no attributes are found or if a loading error occurs.
9939  */
9940 MonoCustomAttrInfo*
9941 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9942 {
9943         MonoError error;
9944         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9945         mono_error_cleanup (&error);
9946         return result;
9947 }
9948 /**
9949  * mono_custom_attrs_from_index_checked:
9950  *
9951  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9952  */
9953 MonoCustomAttrInfo*
9954 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9955 {
9956         guint32 mtoken, i, len;
9957         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9958         MonoTableInfo *ca;
9959         MonoCustomAttrInfo *ainfo;
9960         GList *tmp, *list = NULL;
9961         const char *data;
9962         MonoCustomAttrEntry* attr;
9963
9964         mono_error_init (error);
9965
9966         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9967
9968         i = mono_metadata_custom_attrs_from_index (image, idx);
9969         if (!i)
9970                 return NULL;
9971         i --;
9972         while (i < ca->rows) {
9973                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9974                         break;
9975                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9976                 ++i;
9977         }
9978         len = g_list_length (list);
9979         if (!len)
9980                 return NULL;
9981         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9982         ainfo->num_attrs = len;
9983         ainfo->image = image;
9984         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9985                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9986                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9987                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9988                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9989                         mtoken |= MONO_TOKEN_METHOD_DEF;
9990                         break;
9991                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9992                         mtoken |= MONO_TOKEN_MEMBER_REF;
9993                         break;
9994                 default:
9995                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9996                         break;
9997                 }
9998                 attr = &ainfo->attrs [i - 1];
9999                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
10000                 if (!attr->ctor) {
10001                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
10002                         g_list_free (list);
10003                         g_free (ainfo);
10004                         return NULL;
10005                 }
10006
10007                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
10008                         /*FIXME raising an exception here doesn't make any sense*/
10009                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
10010                         g_list_free (list);
10011                         g_free (ainfo);
10012                         return NULL;
10013                 }
10014                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
10015                 attr->data_size = mono_metadata_decode_value (data, &data);
10016                 attr->data = (guchar*)data;
10017         }
10018         g_list_free (list);
10019
10020         return ainfo;
10021 }
10022
10023 MonoCustomAttrInfo*
10024 mono_custom_attrs_from_method (MonoMethod *method)
10025 {
10026         MonoError error;
10027         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
10028         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10029         return result;
10030 }
10031
10032 MonoCustomAttrInfo*
10033 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
10034 {
10035         guint32 idx;
10036
10037         mono_error_init (error);
10038
10039         /*
10040          * An instantiated method has the same cattrs as the generic method definition.
10041          *
10042          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10043          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10044          */
10045         if (method->is_inflated)
10046                 method = ((MonoMethodInflated *) method)->declaring;
10047         
10048         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
10049                 return lookup_custom_attr (method->klass->image, method);
10050
10051         if (!method->token)
10052                 /* Synthetic methods */
10053                 return NULL;
10054
10055         idx = mono_method_get_index (method);
10056         idx <<= MONO_CUSTOM_ATTR_BITS;
10057         idx |= MONO_CUSTOM_ATTR_METHODDEF;
10058         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
10059 }
10060
10061 MonoCustomAttrInfo*
10062 mono_custom_attrs_from_class (MonoClass *klass)
10063 {
10064         MonoError error;
10065         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
10066         mono_error_cleanup (&error);
10067         return result;
10068 }
10069
10070 MonoCustomAttrInfo*
10071 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
10072 {
10073         guint32 idx;
10074
10075         mono_error_init (error);
10076
10077         if (klass->generic_class)
10078                 klass = klass->generic_class->container_class;
10079
10080         if (image_is_dynamic (klass->image))
10081                 return lookup_custom_attr (klass->image, klass);
10082
10083         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
10084                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
10085                 idx <<= MONO_CUSTOM_ATTR_BITS;
10086                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10087         } else {
10088                 idx = mono_metadata_token_index (klass->type_token);
10089                 idx <<= MONO_CUSTOM_ATTR_BITS;
10090                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10091         }
10092         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10093 }
10094
10095 MonoCustomAttrInfo*
10096 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10097 {
10098         MonoError error;
10099         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10100         mono_error_cleanup (&error);
10101         return result;
10102 }
10103
10104 MonoCustomAttrInfo*
10105 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10106 {
10107         guint32 idx;
10108         
10109         mono_error_init (error);
10110
10111         if (image_is_dynamic (assembly->image))
10112                 return lookup_custom_attr (assembly->image, assembly);
10113         idx = 1; /* there is only one assembly */
10114         idx <<= MONO_CUSTOM_ATTR_BITS;
10115         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10116         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10117 }
10118
10119 static MonoCustomAttrInfo*
10120 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10121 {
10122         guint32 idx;
10123         
10124         if (image_is_dynamic (image))
10125                 return lookup_custom_attr (image, image);
10126         idx = 1; /* there is only one module */
10127         idx <<= MONO_CUSTOM_ATTR_BITS;
10128         idx |= MONO_CUSTOM_ATTR_MODULE;
10129         return mono_custom_attrs_from_index_checked (image, idx, error);
10130 }
10131
10132 MonoCustomAttrInfo*
10133 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10134 {
10135         MonoError error;
10136         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10137         mono_error_cleanup (&error);
10138         return result;
10139 }
10140
10141 MonoCustomAttrInfo*
10142 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10143 {
10144         guint32 idx;
10145         
10146         if (image_is_dynamic (klass->image)) {
10147                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10148                 return lookup_custom_attr (klass->image, property);
10149         }
10150         idx = find_property_index (klass, property);
10151         idx <<= MONO_CUSTOM_ATTR_BITS;
10152         idx |= MONO_CUSTOM_ATTR_PROPERTY;
10153         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10154 }
10155
10156 MonoCustomAttrInfo*
10157 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10158 {
10159         MonoError error;
10160         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10161         mono_error_cleanup (&error);
10162         return result;
10163 }
10164
10165 MonoCustomAttrInfo*
10166 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10167 {
10168         guint32 idx;
10169         
10170         if (image_is_dynamic (klass->image)) {
10171                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10172                 return lookup_custom_attr (klass->image, event);
10173         }
10174         idx = find_event_index (klass, event);
10175         idx <<= MONO_CUSTOM_ATTR_BITS;
10176         idx |= MONO_CUSTOM_ATTR_EVENT;
10177         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10178 }
10179
10180 MonoCustomAttrInfo*
10181 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10182 {
10183         MonoError error;
10184         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10185         mono_error_cleanup (&error);
10186         return result;
10187 }
10188
10189 MonoCustomAttrInfo*
10190 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10191 {
10192         guint32 idx;
10193         mono_error_init (error);
10194
10195         if (image_is_dynamic (klass->image)) {
10196                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10197                 return lookup_custom_attr (klass->image, field);
10198         }
10199         idx = find_field_index (klass, field);
10200         idx <<= MONO_CUSTOM_ATTR_BITS;
10201         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10202         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10203 }
10204
10205 /**
10206  * mono_custom_attrs_from_param:
10207  * @method: handle to the method that we want to retrieve custom parameter information from
10208  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10209  *
10210  * The result must be released with mono_custom_attrs_free().
10211  *
10212  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10213  */
10214 MonoCustomAttrInfo*
10215 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10216 {
10217         MonoError error;
10218         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10219         mono_error_cleanup (&error);
10220         return result;
10221 }
10222
10223 /**
10224  * mono_custom_attrs_from_param_checked:
10225  * @method: handle to the method that we want to retrieve custom parameter information from
10226  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10227  * @error: set on error
10228  *
10229  * The result must be released with mono_custom_attrs_free().
10230  *
10231  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
10232  */
10233 MonoCustomAttrInfo*
10234 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10235 {
10236         MonoTableInfo *ca;
10237         guint32 i, idx, method_index;
10238         guint32 param_list, param_last, param_pos, found;
10239         MonoImage *image;
10240         MonoReflectionMethodAux *aux;
10241
10242         mono_error_init (error);
10243
10244         /*
10245          * An instantiated method has the same cattrs as the generic method definition.
10246          *
10247          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10248          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10249          */
10250         if (method->is_inflated)
10251                 method = ((MonoMethodInflated *) method)->declaring;
10252
10253         if (image_is_dynamic (method->klass->image)) {
10254                 MonoCustomAttrInfo *res, *ainfo;
10255                 int size;
10256
10257                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10258                 if (!aux || !aux->param_cattr)
10259                         return NULL;
10260
10261                 /* Need to copy since it will be freed later */
10262                 ainfo = aux->param_cattr [param];
10263                 if (!ainfo)
10264                         return NULL;
10265                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10266                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10267                 memcpy (res, ainfo, size);
10268                 return res;
10269         }
10270
10271         image = method->klass->image;
10272         method_index = mono_method_get_index (method);
10273         if (!method_index)
10274                 return NULL;
10275         ca = &image->tables [MONO_TABLE_METHOD];
10276
10277         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10278         if (method_index == ca->rows) {
10279                 ca = &image->tables [MONO_TABLE_PARAM];
10280                 param_last = ca->rows + 1;
10281         } else {
10282                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10283                 ca = &image->tables [MONO_TABLE_PARAM];
10284         }
10285         found = FALSE;
10286         for (i = param_list; i < param_last; ++i) {
10287                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10288                 if (param_pos == param) {
10289                         found = TRUE;
10290                         break;
10291                 }
10292         }
10293         if (!found)
10294                 return NULL;
10295         idx = i;
10296         idx <<= MONO_CUSTOM_ATTR_BITS;
10297         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10298         return mono_custom_attrs_from_index_checked (image, idx, error);
10299 }
10300
10301 gboolean
10302 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10303 {
10304         int i;
10305         MonoClass *klass;
10306         for (i = 0; i < ainfo->num_attrs; ++i) {
10307                 klass = ainfo->attrs [i].ctor->klass;
10308                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10309                         return TRUE;
10310         }
10311         return FALSE;
10312 }
10313
10314 MonoObject*
10315 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10316 {
10317         MonoError error;
10318         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10319         mono_error_assert_ok (&error); /*FIXME proper error handling*/
10320         return res;
10321 }
10322
10323 MonoObject*
10324 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10325 {
10326         int i, attr_index;
10327         MonoClass *klass;
10328         MonoArray *attrs;
10329
10330         mono_error_init (error);
10331
10332         attr_index = -1;
10333         for (i = 0; i < ainfo->num_attrs; ++i) {
10334                 klass = ainfo->attrs [i].ctor->klass;
10335                 if (mono_class_has_parent (klass, attr_klass)) {
10336                         attr_index = i;
10337                         break;
10338                 }
10339         }
10340         if (attr_index == -1)
10341                 return NULL;
10342
10343         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10344         if (!mono_error_ok (error))
10345                 return NULL;
10346         return mono_array_get (attrs, MonoObject*, attr_index);
10347 }
10348
10349 /*
10350  * mono_reflection_get_custom_attrs_info:
10351  * @obj: a reflection object handle
10352  *
10353  * Return the custom attribute info for attributes defined for the
10354  * reflection handle @obj. The objects.
10355  *
10356  * FIXME this function leaks like a sieve for SRE objects.
10357  */
10358 MonoCustomAttrInfo*
10359 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10360 {
10361         MonoError error;
10362         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10363         mono_error_assert_ok (&error);
10364         return result;
10365 }
10366
10367 /**
10368  * mono_reflection_get_custom_attrs_info_checked:
10369  * @obj: a reflection object handle
10370  * @error: set on error
10371  *
10372  * Return the custom attribute info for attributes defined for the
10373  * reflection handle @obj. The objects.
10374  *
10375  * On failure returns NULL and sets @error.
10376  *
10377  * FIXME this function leaks like a sieve for SRE objects.
10378  */
10379 MonoCustomAttrInfo*
10380 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10381 {
10382         MonoClass *klass;
10383         MonoCustomAttrInfo *cinfo = NULL;
10384         
10385         mono_error_init (error);
10386
10387         klass = obj->vtable->klass;
10388         if (klass == mono_defaults.runtimetype_class) {
10389                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10390                 return_val_if_nok (error, NULL);
10391                 klass = mono_class_from_mono_type (type);
10392                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10393                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10394                 return_val_if_nok (error, NULL);
10395         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10396                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10397                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10398                 return_val_if_nok (error, NULL);
10399         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10400                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10401                 cinfo = mono_custom_attrs_from_module (module->image, error);
10402                 return_val_if_nok (error, NULL);
10403         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10404                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10405                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10406                 return_val_if_nok (error, NULL);
10407         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10408                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10409                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10410                 return_val_if_nok (error, NULL);
10411         } else if (strcmp ("MonoField", klass->name) == 0) {
10412                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10413                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10414                 return_val_if_nok (error, NULL);
10415         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10416                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10417                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10418                 return_val_if_nok (error, NULL);
10419         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10420                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10421                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10422                 return_val_if_nok (error, NULL);
10423         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10424                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10425                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10426                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10427                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10428                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10429                         return_val_if_nok (error, NULL);
10430                 } else if (is_sr_mono_property (member_class)) {
10431                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10432                         MonoMethod *method;
10433                         if (!(method = prop->property->get))
10434                                 method = prop->property->set;
10435                         g_assert (method);
10436
10437                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10438                         return_val_if_nok (error, NULL);
10439                 } 
10440 #ifndef DISABLE_REFLECTION_EMIT
10441                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10442                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10443                         return_val_if_nok (error, NULL);
10444                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10445                         return_val_if_nok (error, NULL);
10446                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10447                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10448                         MonoMethod *method = NULL;
10449                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10450                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10451                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10452                                 method = ((MonoReflectionMethod *)c->cb)->method;
10453                         else
10454                                 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));
10455
10456                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10457                         return_val_if_nok (error, NULL);
10458                 } 
10459 #endif
10460                 else {
10461                         char *type_name = mono_type_get_full_name (member_class);
10462                         mono_error_set_not_supported (error,
10463                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10464                                                       type_name);
10465                         g_free (type_name);
10466                         return NULL;
10467                 }
10468         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10469                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10470                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10471         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10472                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10473                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10474         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10475                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10476                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10477         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10478                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10479                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10480         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10481                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10482                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10483         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10484                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10485                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10486         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10487                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10488                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10489                 return_val_if_nok (error, NULL);
10490         } else { /* handle other types here... */
10491                 g_error ("get custom attrs not yet supported for %s", klass->name);
10492         }
10493
10494         return cinfo;
10495 }
10496
10497 /*
10498  * mono_reflection_get_custom_attrs_by_type:
10499  * @obj: a reflection object handle
10500  *
10501  * Return an array with all the custom attributes defined of the
10502  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10503  * of that type are returned. The objects are fully build. Return NULL if a loading error
10504  * occurs.
10505  */
10506 MonoArray*
10507 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10508 {
10509         MonoArray *result;
10510         MonoCustomAttrInfo *cinfo;
10511
10512         mono_error_init (error);
10513
10514         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10515         return_val_if_nok (error, NULL);
10516         if (cinfo) {
10517                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10518                 if (!cinfo->cached)
10519                         mono_custom_attrs_free (cinfo);
10520                 if (!result)
10521                         return NULL;
10522         } else {
10523                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
10524         }
10525
10526         return result;
10527 }
10528
10529 /*
10530  * mono_reflection_get_custom_attrs:
10531  * @obj: a reflection object handle
10532  *
10533  * Return an array with all the custom attributes defined of the
10534  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10535  * occurs.
10536  */
10537 MonoArray*
10538 mono_reflection_get_custom_attrs (MonoObject *obj)
10539 {
10540         MonoError error;
10541
10542         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10543 }
10544
10545 /*
10546  * mono_reflection_get_custom_attrs_data:
10547  * @obj: a reflection obj handle
10548  *
10549  * Returns an array of System.Reflection.CustomAttributeData,
10550  * which include information about attributes reflected on
10551  * types loaded using the Reflection Only methods
10552  */
10553 MonoArray*
10554 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10555 {
10556         MonoError error;
10557         MonoArray* result;
10558         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10559         mono_error_cleanup (&error);
10560         return result;
10561 }
10562
10563 /*
10564  * mono_reflection_get_custom_attrs_data_checked:
10565  * @obj: a reflection obj handle
10566  * @error: set on error
10567  *
10568  * Returns an array of System.Reflection.CustomAttributeData,
10569  * which include information about attributes reflected on
10570  * types loaded using the Reflection Only methods
10571  */
10572 MonoArray*
10573 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10574 {
10575         MonoArray *result;
10576         MonoCustomAttrInfo *cinfo;
10577
10578         mono_error_init (error);
10579
10580         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10581         return_val_if_nok (error, NULL);
10582         if (cinfo) {
10583                 result = mono_custom_attrs_data_construct (cinfo, error);
10584                 if (!cinfo->cached)
10585                         mono_custom_attrs_free (cinfo);
10586                 return_val_if_nok (error, NULL);
10587         } else 
10588                 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
10589
10590         return result;
10591 }
10592
10593 static MonoReflectionType*
10594 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10595 {
10596         static MonoMethod *method_get_underlying_system_type = NULL;
10597         MonoReflectionType *rt;
10598         MonoMethod *usertype_method;
10599
10600         mono_error_init (error);
10601
10602         if (!method_get_underlying_system_type)
10603                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10604
10605         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10606
10607         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10608
10609         return rt;
10610 }
10611
10612
10613 static gboolean
10614 is_corlib_type (MonoClass *klass)
10615 {
10616         return klass->image == mono_defaults.corlib;
10617 }
10618
10619 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10620         static MonoClass *cached_class; \
10621         if (cached_class) \
10622                 return cached_class == _class; \
10623         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10624                 cached_class = _class; \
10625                 return TRUE; \
10626         } \
10627         return FALSE; \
10628 } while (0) \
10629
10630
10631 #ifndef DISABLE_REFLECTION_EMIT
10632 static gboolean
10633 is_sre_array (MonoClass *klass)
10634 {
10635         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10636 }
10637
10638 static gboolean
10639 is_sre_byref (MonoClass *klass)
10640 {
10641         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10642 }
10643
10644 static gboolean
10645 is_sre_pointer (MonoClass *klass)
10646 {
10647         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10648 }
10649
10650 static gboolean
10651 is_sre_generic_instance (MonoClass *klass)
10652 {
10653         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10654 }
10655
10656 static gboolean
10657 is_sre_type_builder (MonoClass *klass)
10658 {
10659         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10660 }
10661
10662 static gboolean
10663 is_sre_method_builder (MonoClass *klass)
10664 {
10665         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10666 }
10667
10668 static gboolean
10669 is_sre_ctor_builder (MonoClass *klass)
10670 {
10671         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10672 }
10673
10674 static gboolean
10675 is_sre_field_builder (MonoClass *klass)
10676 {
10677         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10678 }
10679
10680 static gboolean
10681 is_sre_method_on_tb_inst (MonoClass *klass)
10682 {
10683         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10684 }
10685
10686 static gboolean
10687 is_sre_ctor_on_tb_inst (MonoClass *klass)
10688 {
10689         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10690 }
10691
10692 MonoType*
10693 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10694 {
10695         MonoClass *klass;
10696         mono_error_init (error);
10697
10698         if (!ref)
10699                 return NULL;
10700         if (ref->type)
10701                 return ref->type;
10702
10703         if (is_usertype (ref)) {
10704                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10705                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10706                         return NULL;
10707                 if (ref->type)
10708                         return ref->type;
10709         }
10710
10711         klass = mono_object_class (ref);
10712
10713         if (is_sre_array (klass)) {
10714                 MonoType *res;
10715                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10716                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10717                 return_val_if_nok (error, NULL);
10718                 g_assert (base);
10719                 if (sre_array->rank == 0) //single dimentional array
10720                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10721                 else
10722                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10723                 sre_array->type.type = res;
10724                 return res;
10725         } else if (is_sre_byref (klass)) {
10726                 MonoType *res;
10727                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10728                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10729                 return_val_if_nok (error, NULL);
10730                 g_assert (base);
10731                 res = &mono_class_from_mono_type (base)->this_arg;
10732                 sre_byref->type.type = res;
10733                 return res;
10734         } else if (is_sre_pointer (klass)) {
10735                 MonoType *res;
10736                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10737                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10738                 return_val_if_nok (error, NULL);
10739                 g_assert (base);
10740                 res = &mono_ptr_class_get (base)->byval_arg;
10741                 sre_pointer->type.type = res;
10742                 return res;
10743         } else if (is_sre_generic_instance (klass)) {
10744                 MonoType *res, **types;
10745                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10746                 int i, count;
10747
10748                 count = mono_array_length (gclass->type_arguments);
10749                 types = g_new0 (MonoType*, count);
10750                 for (i = 0; i < count; ++i) {
10751                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10752                         types [i] = mono_reflection_type_get_handle (t, error);
10753                         if (!types[i] || !is_ok (error)) {
10754                                 g_free (types);
10755                                 return NULL;
10756                         }
10757                 }
10758
10759                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10760                 g_free (types);
10761                 g_assert (res);
10762                 gclass->type.type = res;
10763                 return res;
10764         }
10765
10766         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10767         return NULL;
10768 }
10769
10770 void
10771 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10772 {
10773         MonoError error;
10774         mono_reflection_type_get_handle (type, &error);
10775         mono_error_set_pending_exception (&error);
10776 }
10777
10778 static gboolean
10779 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10780 {
10781         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10782         MonoClass *klass;
10783
10784         mono_error_init (error);
10785
10786         MonoType *res = mono_reflection_type_get_handle (type, error);
10787
10788         if (!res && is_ok (error)) {
10789                 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10790         }
10791         return_val_if_nok (error, FALSE);
10792
10793         klass = mono_class_from_mono_type (res);
10794
10795         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10796         mono_domain_lock (domain);
10797
10798         if (!image_is_dynamic (klass->image)) {
10799                 mono_class_setup_supertypes (klass);
10800         } else {
10801                 if (!domain->type_hash)
10802                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10803                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10804                 mono_g_hash_table_insert (domain->type_hash, res, type);
10805         }
10806         mono_domain_unlock (domain);
10807         mono_loader_unlock ();
10808
10809         return TRUE;
10810 }
10811
10812 void
10813 mono_reflection_register_with_runtime (MonoReflectionType *type)
10814 {
10815         MonoError error;
10816         (void) reflection_register_with_runtime (type, &error);
10817         mono_error_set_pending_exception (&error);
10818 }
10819
10820 /**
10821  * LOCKING: Assumes the loader lock is held.
10822  */
10823 static MonoMethodSignature*
10824 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10825         MonoMethodSignature *sig;
10826         int count, i;
10827
10828         mono_error_init (error);
10829
10830         count = parameters? mono_array_length (parameters): 0;
10831
10832         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10833         sig->param_count = count;
10834         sig->sentinelpos = -1; /* FIXME */
10835         for (i = 0; i < count; ++i) {
10836                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10837                 if (!is_ok (error)) {
10838                         image_g_free (image, sig);
10839                         return NULL;
10840                 }
10841         }
10842         return sig;
10843 }
10844
10845 /**
10846  * LOCKING: Assumes the loader lock is held.
10847  */
10848 static MonoMethodSignature*
10849 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10850         MonoMethodSignature *sig;
10851
10852         mono_error_init (error);
10853
10854         sig = parameters_to_signature (image, ctor->parameters, error);
10855         return_val_if_nok (error, NULL);
10856         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10857         sig->ret = &mono_defaults.void_class->byval_arg;
10858         return sig;
10859 }
10860
10861 /**
10862  * LOCKING: Assumes the loader lock is held.
10863  */
10864 static MonoMethodSignature*
10865 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10866         MonoMethodSignature *sig;
10867
10868         mono_error_init (error);
10869
10870         sig = parameters_to_signature (image, method->parameters, error);
10871         return_val_if_nok (error, NULL);
10872         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10873         if (method->rtype) {
10874                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10875                 if (!is_ok (error)) {
10876                         image_g_free (image, sig);
10877                         return NULL;
10878                 }
10879         } else {
10880                 sig->ret = &mono_defaults.void_class->byval_arg;
10881         }
10882         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10883         return sig;
10884 }
10885
10886 static MonoMethodSignature*
10887 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10888         MonoMethodSignature *sig;
10889
10890         mono_error_init (error);
10891
10892         sig = parameters_to_signature (NULL, method->parameters, error);
10893         return_val_if_nok (error, NULL);
10894         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10895         if (method->rtype) {
10896                 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10897                 if (!is_ok (error)) {
10898                         g_free (sig);
10899                         return NULL;
10900                 }
10901         } else {
10902                 sig->ret = &mono_defaults.void_class->byval_arg;
10903         }
10904         sig->generic_param_count = 0;
10905         return sig;
10906 }
10907
10908 static void
10909 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10910 {
10911         mono_error_init (error);
10912         MonoClass *klass = mono_object_class (prop);
10913         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10914                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10915                 *name = mono_string_to_utf8_checked (pb->name, error);
10916                 return_if_nok (error);
10917                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10918         } else {
10919                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10920                 *name = g_strdup (p->property->name);
10921                 if (p->property->get)
10922                         *type = mono_method_signature (p->property->get)->ret;
10923                 else
10924                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10925         }
10926 }
10927
10928 static void
10929 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10930 {
10931         mono_error_init (error);
10932         MonoClass *klass = mono_object_class (field);
10933         if (strcmp (klass->name, "FieldBuilder") == 0) {
10934                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10935                 *name = mono_string_to_utf8_checked (fb->name, error);
10936                 return_if_nok (error);
10937                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10938         } else {
10939                 MonoReflectionField *f = (MonoReflectionField *)field;
10940                 *name = g_strdup (mono_field_get_name (f->field));
10941                 *type = f->field->type;
10942         }
10943 }
10944
10945 #else /* DISABLE_REFLECTION_EMIT */
10946
10947 void
10948 mono_reflection_register_with_runtime (MonoReflectionType *type)
10949 {
10950         /* This is empty */
10951 }
10952
10953 static gboolean
10954 is_sre_type_builder (MonoClass *klass)
10955 {
10956         return FALSE;
10957 }
10958
10959 static gboolean
10960 is_sre_generic_instance (MonoClass *klass)
10961 {
10962         return FALSE;
10963 }
10964
10965 static void
10966 init_type_builder_generics (MonoObject *type, MonoError *error)
10967 {
10968         mono_error_init (error);
10969 }
10970
10971 #endif /* !DISABLE_REFLECTION_EMIT */
10972
10973
10974 static gboolean
10975 is_sr_mono_field (MonoClass *klass)
10976 {
10977         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10978 }
10979
10980 static gboolean
10981 is_sr_mono_property (MonoClass *klass)
10982 {
10983         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10984 }
10985
10986 static gboolean
10987 is_sr_mono_method (MonoClass *klass)
10988 {
10989         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10990 }
10991
10992 static gboolean
10993 is_sr_mono_cmethod (MonoClass *klass)
10994 {
10995         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10996 }
10997
10998 static gboolean
10999 is_sr_mono_generic_method (MonoClass *klass)
11000 {
11001         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
11002 }
11003
11004 static gboolean
11005 is_sr_mono_generic_cmethod (MonoClass *klass)
11006 {
11007         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
11008 }
11009
11010 gboolean
11011 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
11012 {
11013         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
11014 }
11015
11016 static gboolean
11017 is_usertype (MonoReflectionType *ref)
11018 {
11019         MonoClass *klass = mono_object_class (ref);
11020         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
11021 }
11022
11023 static MonoReflectionType*
11024 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
11025 {
11026         mono_error_init (error);
11027         if (!type || type->type)
11028                 return type;
11029
11030         if (is_usertype (type)) {
11031                 type = mono_reflection_type_get_underlying_system_type (type, error);
11032                 return_val_if_nok (error, NULL);
11033                 if (is_usertype (type)) {
11034                         mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
11035                         return NULL;
11036                 }
11037         }
11038
11039         return type;
11040 }
11041 /**
11042  * encode_cattr_value:
11043  * Encode a value in a custom attribute stream of bytes.
11044  * The value to encode is either supplied as an object in argument val
11045  * (valuetypes are boxed), or as a pointer to the data in the
11046  * argument argval.
11047  * @type represents the type of the value
11048  * @buffer is the start of the buffer
11049  * @p the current position in the buffer
11050  * @buflen contains the size of the buffer and is used to return the new buffer size
11051  * if this needs to be realloced.
11052  * @retbuffer and @retp return the start and the position of the buffer
11053  * @error set on error.
11054  */
11055 static void
11056 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
11057 {
11058         MonoTypeEnum simple_type;
11059         
11060         mono_error_init (error);
11061         if ((p-buffer) + 10 >= *buflen) {
11062                 char *newbuf;
11063                 *buflen *= 2;
11064                 newbuf = (char *)g_realloc (buffer, *buflen);
11065                 p = newbuf + (p-buffer);
11066                 buffer = newbuf;
11067         }
11068         if (!argval)
11069                 argval = ((char*)arg + sizeof (MonoObject));
11070         simple_type = type->type;
11071 handle_enum:
11072         switch (simple_type) {
11073         case MONO_TYPE_BOOLEAN:
11074         case MONO_TYPE_U1:
11075         case MONO_TYPE_I1:
11076                 *p++ = *argval;
11077                 break;
11078         case MONO_TYPE_CHAR:
11079         case MONO_TYPE_U2:
11080         case MONO_TYPE_I2:
11081                 swap_with_size (p, argval, 2, 1);
11082                 p += 2;
11083                 break;
11084         case MONO_TYPE_U4:
11085         case MONO_TYPE_I4:
11086         case MONO_TYPE_R4:
11087                 swap_with_size (p, argval, 4, 1);
11088                 p += 4;
11089                 break;
11090         case MONO_TYPE_R8:
11091                 swap_with_size (p, argval, 8, 1);
11092                 p += 8;
11093                 break;
11094         case MONO_TYPE_U8:
11095         case MONO_TYPE_I8:
11096                 swap_with_size (p, argval, 8, 1);
11097                 p += 8;
11098                 break;
11099         case MONO_TYPE_VALUETYPE:
11100                 if (type->data.klass->enumtype) {
11101                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
11102                         goto handle_enum;
11103                 } else {
11104                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11105                 }
11106                 break;
11107         case MONO_TYPE_STRING: {
11108                 char *str;
11109                 guint32 slen;
11110                 if (!arg) {
11111                         *p++ = 0xFF;
11112                         break;
11113                 }
11114                 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
11115                 return_if_nok (error);
11116                 slen = strlen (str);
11117                 if ((p-buffer) + 10 + slen >= *buflen) {
11118                         char *newbuf;
11119                         *buflen *= 2;
11120                         *buflen += slen;
11121                         newbuf = (char *)g_realloc (buffer, *buflen);
11122                         p = newbuf + (p-buffer);
11123                         buffer = newbuf;
11124                 }
11125                 mono_metadata_encode_value (slen, p, &p);
11126                 memcpy (p, str, slen);
11127                 p += slen;
11128                 g_free (str);
11129                 break;
11130         }
11131         case MONO_TYPE_CLASS: {
11132                 char *str;
11133                 guint32 slen;
11134                 MonoType *arg_type;
11135                 if (!arg) {
11136                         *p++ = 0xFF;
11137                         break;
11138                 }
11139 handle_type:
11140                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11141                 return_if_nok (error);
11142
11143                 str = type_get_qualified_name (arg_type, NULL);
11144                 slen = strlen (str);
11145                 if ((p-buffer) + 10 + slen >= *buflen) {
11146                         char *newbuf;
11147                         *buflen *= 2;
11148                         *buflen += slen;
11149                         newbuf = (char *)g_realloc (buffer, *buflen);
11150                         p = newbuf + (p-buffer);
11151                         buffer = newbuf;
11152                 }
11153                 mono_metadata_encode_value (slen, p, &p);
11154                 memcpy (p, str, slen);
11155                 p += slen;
11156                 g_free (str);
11157                 break;
11158         }
11159         case MONO_TYPE_SZARRAY: {
11160                 int len, i;
11161                 MonoClass *eclass, *arg_eclass;
11162
11163                 if (!arg) {
11164                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11165                         break;
11166                 }
11167                 len = mono_array_length ((MonoArray*)arg);
11168                 *p++ = len & 0xff;
11169                 *p++ = (len >> 8) & 0xff;
11170                 *p++ = (len >> 16) & 0xff;
11171                 *p++ = (len >> 24) & 0xff;
11172                 *retp = p;
11173                 *retbuffer = buffer;
11174                 eclass = type->data.klass;
11175                 arg_eclass = mono_object_class (arg)->element_class;
11176
11177                 if (!eclass) {
11178                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11179                         eclass = mono_defaults.object_class;
11180                 }
11181                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11182                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11183                         int elsize = mono_class_array_element_size (arg_eclass);
11184                         for (i = 0; i < len; ++i) {
11185                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11186                                 return_if_nok (error);
11187                                 elptr += elsize;
11188                         }
11189                 } else if (eclass->valuetype && arg_eclass->valuetype) {
11190                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11191                         int elsize = mono_class_array_element_size (eclass);
11192                         for (i = 0; i < len; ++i) {
11193                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11194                                 return_if_nok (error);
11195                                 elptr += elsize;
11196                         }
11197                 } else {
11198                         for (i = 0; i < len; ++i) {
11199                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11200                                 return_if_nok (error);
11201                         }
11202                 }
11203                 break;
11204         }
11205         case MONO_TYPE_OBJECT: {
11206                 MonoClass *klass;
11207                 char *str;
11208                 guint32 slen;
11209
11210                 /*
11211                  * The parameter type is 'object' but the type of the actual
11212                  * argument is not. So we have to add type information to the blob
11213                  * too. This is completely undocumented in the spec.
11214                  */
11215
11216                 if (arg == NULL) {
11217                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
11218                         *p++ = 0xFF;
11219                         break;
11220                 }
11221                 
11222                 klass = mono_object_class (arg);
11223
11224                 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11225                         *p++ = 0x50;
11226                         goto handle_type;
11227                 } else {
11228                         return_if_nok (error);
11229                 }
11230
11231                 if (klass->enumtype) {
11232                         *p++ = 0x55;
11233                 } else if (klass == mono_defaults.string_class) {
11234                         simple_type = MONO_TYPE_STRING;
11235                         *p++ = 0x0E;
11236                         goto handle_enum;
11237                 } else if (klass->rank == 1) {
11238                         *p++ = 0x1D;
11239                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11240                                 /* See Partition II, Appendix B3 */
11241                                 *p++ = 0x51;
11242                         else
11243                                 *p++ = klass->element_class->byval_arg.type;
11244                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11245                         return_if_nok (error);
11246                         break;
11247                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11248                         *p++ = simple_type = klass->byval_arg.type;
11249                         goto handle_enum;
11250                 } else {
11251                         g_error ("unhandled type in custom attr");
11252                 }
11253                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11254                 slen = strlen (str);
11255                 if ((p-buffer) + 10 + slen >= *buflen) {
11256                         char *newbuf;
11257                         *buflen *= 2;
11258                         *buflen += slen;
11259                         newbuf = (char *)g_realloc (buffer, *buflen);
11260                         p = newbuf + (p-buffer);
11261                         buffer = newbuf;
11262                 }
11263                 mono_metadata_encode_value (slen, p, &p);
11264                 memcpy (p, str, slen);
11265                 p += slen;
11266                 g_free (str);
11267                 simple_type = mono_class_enum_basetype (klass)->type;
11268                 goto handle_enum;
11269         }
11270         default:
11271                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11272         }
11273         *retp = p;
11274         *retbuffer = buffer;
11275 }
11276
11277 static void
11278 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11279 {
11280         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11281                 char *str = type_get_qualified_name (type, NULL);
11282                 int slen = strlen (str);
11283
11284                 *p++ = 0x55;
11285                 /*
11286                  * This seems to be optional...
11287                  * *p++ = 0x80;
11288                  */
11289                 mono_metadata_encode_value (slen, p, &p);
11290                 memcpy (p, str, slen);
11291                 p += slen;
11292                 g_free (str);
11293         } else if (type->type == MONO_TYPE_OBJECT) {
11294                 *p++ = 0x51;
11295         } else if (type->type == MONO_TYPE_CLASS) {
11296                 /* it should be a type: encode_cattr_value () has the check */
11297                 *p++ = 0x50;
11298         } else {
11299                 mono_metadata_encode_value (type->type, p, &p);
11300                 if (type->type == MONO_TYPE_SZARRAY)
11301                         /* See the examples in Partition VI, Annex B */
11302                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11303         }
11304
11305         *retp = p;
11306 }
11307
11308 #ifndef DISABLE_REFLECTION_EMIT
11309 static void
11310 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11311 {
11312         int len;
11313
11314         mono_error_init (error);
11315
11316         /* Preallocate a large enough buffer */
11317         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11318                 char *str = type_get_qualified_name (type, NULL);
11319                 len = strlen (str);
11320                 g_free (str);
11321         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11322                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11323                 len = strlen (str);
11324                 g_free (str);
11325         } else {
11326                 len = 0;
11327         }
11328         len += strlen (name);
11329
11330         if ((p-buffer) + 20 + len >= *buflen) {
11331                 char *newbuf;
11332                 *buflen *= 2;
11333                 *buflen += len;
11334                 newbuf = (char *)g_realloc (buffer, *buflen);
11335                 p = newbuf + (p-buffer);
11336                 buffer = newbuf;
11337         }
11338
11339         encode_field_or_prop_type (type, p, &p);
11340
11341         len = strlen (name);
11342         mono_metadata_encode_value (len, p, &p);
11343         memcpy (p, name, len);
11344         p += len;
11345         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11346         return_if_nok (error);
11347         *retp = p;
11348         *retbuffer = buffer;
11349 }
11350
11351 /**
11352  * mono_reflection_get_custom_attrs_blob:
11353  * @ctor: custom attribute constructor
11354  * @ctorArgs: arguments o the constructor
11355  * @properties:
11356  * @propValues:
11357  * @fields:
11358  * @fieldValues:
11359  * 
11360  * Creates the blob of data that needs to be saved in the metadata and that represents
11361  * the custom attributed described by @ctor, @ctorArgs etc.
11362  * Returns: a Byte array representing the blob of data.
11363  */
11364 MonoArray*
11365 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11366 {
11367         MonoError error;
11368         MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11369         mono_error_cleanup (&error);
11370         return result;
11371 }
11372
11373 /**
11374  * mono_reflection_get_custom_attrs_blob_checked:
11375  * @ctor: custom attribute constructor
11376  * @ctorArgs: arguments o the constructor
11377  * @properties:
11378  * @propValues:
11379  * @fields:
11380  * @fieldValues:
11381  * @error: set on error
11382  * 
11383  * Creates the blob of data that needs to be saved in the metadata and that represents
11384  * the custom attributed described by @ctor, @ctorArgs etc.
11385  * Returns: a Byte array representing the blob of data.  On failure returns NULL and sets @error.
11386  */
11387 MonoArray*
11388 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error) 
11389 {
11390         MonoArray *result = NULL;
11391         MonoMethodSignature *sig;
11392         MonoObject *arg;
11393         char *buffer, *p;
11394         guint32 buflen, i;
11395
11396         mono_error_init (error);
11397
11398         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11399                 /* sig is freed later so allocate it in the heap */
11400                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11401                 if (!is_ok (error)) {
11402                         g_free (sig);
11403                         return NULL;
11404                 }
11405         } else {
11406                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11407         }
11408
11409         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11410         buflen = 256;
11411         p = buffer = (char *)g_malloc (buflen);
11412         /* write the prolog */
11413         *p++ = 1;
11414         *p++ = 0;
11415         for (i = 0; i < sig->param_count; ++i) {
11416                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11417                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11418                 if (!is_ok (error)) goto leave;
11419         }
11420         i = 0;
11421         if (properties)
11422                 i += mono_array_length (properties);
11423         if (fields)
11424                 i += mono_array_length (fields);
11425         *p++ = i & 0xff;
11426         *p++ = (i >> 8) & 0xff;
11427         if (properties) {
11428                 MonoObject *prop;
11429                 for (i = 0; i < mono_array_length (properties); ++i) {
11430                         MonoType *ptype;
11431                         char *pname;
11432
11433                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11434                         get_prop_name_and_type (prop, &pname, &ptype, error);
11435                         if (!is_ok (error)) goto leave;
11436                         *p++ = 0x54; /* PROPERTY signature */
11437                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11438                         g_free (pname);
11439                         if (!is_ok (error)) goto leave;
11440                 }
11441         }
11442
11443         if (fields) {
11444                 MonoObject *field;
11445                 for (i = 0; i < mono_array_length (fields); ++i) {
11446                         MonoType *ftype;
11447                         char *fname;
11448
11449                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11450                         get_field_name_and_type (field, &fname, &ftype, error);
11451                         if (!is_ok (error)) goto leave;
11452                         *p++ = 0x53; /* FIELD signature */
11453                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11454                         g_free (fname);
11455                         if (!is_ok (error)) goto leave;
11456                 }
11457         }
11458
11459         g_assert (p - buffer <= buflen);
11460         buflen = p - buffer;
11461         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
11462         if (!is_ok (error))
11463                 goto leave;
11464         p = mono_array_addr (result, char, 0);
11465         memcpy (p, buffer, buflen);
11466 leave:
11467         g_free (buffer);
11468         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11469                 g_free (sig);
11470         return result;
11471 }
11472
11473 /**
11474  * reflection_setup_internal_class:
11475  * @tb: a TypeBuilder object
11476  * @error: set on error
11477  *
11478  * Creates a MonoClass that represents the TypeBuilder.
11479  * This is a trick that lets us simplify a lot of reflection code
11480  * (and will allow us to support Build and Run assemblies easier).
11481  *
11482  * Returns TRUE on success. On failure, returns FALSE and sets @error.
11483  */
11484 static gboolean
11485 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11486 {
11487         MonoClass *klass, *parent;
11488
11489         mono_error_init (error);
11490         RESOLVE_TYPE (tb->parent, error);
11491         return_val_if_nok (error, FALSE);
11492
11493         mono_loader_lock ();
11494
11495         if (tb->parent) {
11496                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11497                 if (!is_ok (error)) {
11498                         mono_loader_unlock ();
11499                         return FALSE;
11500                 }
11501                 /* check so we can compile corlib correctly */
11502                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11503                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11504                         parent = parent_type->data.klass;
11505                 } else {
11506                         parent = mono_class_from_mono_type (parent_type);
11507                 }
11508         } else {
11509                 parent = NULL;
11510         }
11511         
11512         /* the type has already being created: it means we just have to change the parent */
11513         if (tb->type.type) {
11514                 klass = mono_class_from_mono_type (tb->type.type);
11515                 klass->parent = NULL;
11516                 /* fool mono_class_setup_parent */
11517                 klass->supertypes = NULL;
11518                 mono_class_setup_parent (klass, parent);
11519                 mono_class_setup_mono_type (klass);
11520                 mono_loader_unlock ();
11521                 return TRUE;
11522         }
11523
11524         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11525
11526         klass->image = &tb->module->dynamic_image->image;
11527
11528         klass->inited = 1; /* we lie to the runtime */
11529         klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11530         if (!is_ok (error))
11531                 goto failure;
11532         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11533         if (!is_ok (error))
11534                 goto failure;
11535         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11536         klass->flags = tb->attrs;
11537         
11538         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11539
11540         klass->element_class = klass;
11541
11542         if (mono_class_get_ref_info (klass) == NULL) {
11543
11544                 mono_class_set_ref_info (klass, tb);
11545
11546                 /* Put into cache so mono_class_get_checked () will find it.
11547                 Skip nested types as those should not be available on the global scope. */
11548                 if (!tb->nesting_type)
11549                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11550
11551                 /*
11552                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11553                 by performing a mono_class_get which does the full resolution.
11554
11555                 Working around this semantics would require us to write a lot of code for no clear advantage.
11556                 */
11557                 mono_image_append_class_to_reflection_info_set (klass);
11558         } else {
11559                 g_assert (mono_class_get_ref_info (klass) == tb);
11560         }
11561
11562         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11563
11564         if (parent != NULL) {
11565                 mono_class_setup_parent (klass, parent);
11566         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11567                 const char *old_n = klass->name;
11568                 /* trick to get relative numbering right when compiling corlib */
11569                 klass->name = "BuildingObject";
11570                 mono_class_setup_parent (klass, mono_defaults.object_class);
11571                 klass->name = old_n;
11572         }
11573
11574         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11575                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11576                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11577                 klass->instance_size = sizeof (MonoObject);
11578                 klass->size_inited = 1;
11579                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11580         }
11581
11582         mono_class_setup_mono_type (klass);
11583
11584         mono_class_setup_supertypes (klass);
11585
11586         /*
11587          * FIXME: handle interfaces.
11588          */
11589
11590         tb->type.type = &klass->byval_arg;
11591
11592         if (tb->nesting_type) {
11593                 g_assert (tb->nesting_type->type);
11594                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11595                 if (!is_ok (error)) goto failure;
11596                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11597         }
11598
11599         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11600
11601         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11602         
11603         mono_loader_unlock ();
11604         return TRUE;
11605
11606 failure:
11607         mono_loader_unlock ();
11608         return FALSE;
11609 }
11610
11611 /**
11612  * mono_reflection_setup_internal_class:
11613  * @tb: a TypeBuilder object
11614  *
11615  * (icall)
11616  * Creates a MonoClass that represents the TypeBuilder.
11617  * This is a trick that lets us simplify a lot of reflection code
11618  * (and will allow us to support Build and Run assemblies easier).
11619  *
11620  */
11621 void
11622 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11623 {
11624         MonoError error;
11625         (void) reflection_setup_internal_class (tb, &error);
11626         mono_error_set_pending_exception (&error);
11627 }
11628
11629 /*
11630  * mono_reflection_setup_generic_class:
11631  * @tb: a TypeBuilder object
11632  *
11633  * Setup the generic class before adding the first generic parameter.
11634  */
11635 void
11636 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11637 {
11638 }
11639
11640 /**
11641  * mono_reflection_create_generic_class:
11642  * @tb: a TypeBuilder object
11643  * @error: set on error
11644  *
11645  * Creates the generic class after all generic parameters have been added.
11646  * On success returns TRUE, on failure returns FALSE and sets @error.
11647  * 
11648  */
11649 gboolean
11650 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11651 {
11652
11653         MonoClass *klass;
11654         int count, i;
11655
11656         mono_error_init (error);
11657
11658         klass = mono_class_from_mono_type (tb->type.type);
11659
11660         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11661
11662         if (klass->generic_container || (count == 0))
11663                 return TRUE;
11664
11665         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11666
11667         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11668
11669         klass->generic_container->owner.klass = klass;
11670         klass->generic_container->type_argc = count;
11671         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11672
11673         klass->is_generic = 1;
11674
11675         for (i = 0; i < count; i++) {
11676                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11677                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
11678                 return_val_if_nok (error, FALSE);
11679                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11680                 klass->generic_container->type_params [i] = *param;
11681                 /*Make sure we are a diferent type instance */
11682                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11683                 klass->generic_container->type_params [i].info.pklass = NULL;
11684                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11685
11686                 g_assert (klass->generic_container->type_params [i].param.owner);
11687         }
11688
11689         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11690         return TRUE;
11691 }
11692
11693 /**
11694  * reflection_create_internal_class:
11695  * @tb: a TypeBuilder object
11696  * @error: set on error
11697  *
11698  * Actually create the MonoClass that is associated with the TypeBuilder.
11699  * On success returns TRUE, on failure returns FALSE and sets @error.
11700  *
11701  */
11702 static gboolean
11703 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11704 {
11705
11706         MonoClass *klass;
11707
11708         mono_error_init (error);
11709         klass = mono_class_from_mono_type (tb->type.type);
11710
11711         mono_loader_lock ();
11712         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11713                 MonoReflectionFieldBuilder *fb;
11714                 MonoClass *ec;
11715                 MonoType *enum_basetype;
11716
11717                 g_assert (tb->fields != NULL);
11718                 g_assert (mono_array_length (tb->fields) >= 1);
11719
11720                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11721
11722                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11723                 if (!is_ok (error)) {
11724                         mono_loader_unlock ();
11725                         return FALSE;
11726                 }
11727                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11728                         mono_loader_unlock ();
11729                         return TRUE;
11730                 }
11731
11732                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11733                 if (!is_ok (error)) {
11734                         mono_loader_unlock ();
11735                         return FALSE;
11736                 }
11737                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11738                 if (!klass->element_class)
11739                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11740
11741                 /*
11742                  * get the element_class from the current corlib.
11743                  */
11744                 ec = default_class_from_mono_type (enum_basetype);
11745                 klass->instance_size = ec->instance_size;
11746                 klass->size_inited = 1;
11747                 /* 
11748                  * this is almost safe to do with enums and it's needed to be able
11749                  * to create objects of the enum type (for use in SetConstant).
11750                  */
11751                 /* FIXME: Does this mean enums can't have method overrides ? */
11752                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11753         }
11754         mono_loader_unlock ();
11755         return TRUE;
11756 }
11757
11758 /**
11759  * mono_reflection_create_internal_class:
11760  * @tb: a TypeBuilder object
11761  *
11762  * (icall)
11763  * Actually create the MonoClass that is associated with the TypeBuilder.
11764  */
11765 void
11766 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11767 {
11768         MonoError error;
11769         (void) reflection_create_internal_class (tb, &error);
11770         mono_error_set_pending_exception (&error);
11771 }
11772
11773 static MonoMarshalSpec*
11774 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11775                                 MonoReflectionMarshal *minfo, MonoError *error)
11776 {
11777         MonoMarshalSpec *res;
11778
11779         mono_error_init (error);
11780
11781         res = image_g_new0 (image, MonoMarshalSpec, 1);
11782         res->native = (MonoMarshalNative)minfo->type;
11783
11784         switch (minfo->type) {
11785         case MONO_NATIVE_LPARRAY:
11786                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11787                 if (minfo->has_size) {
11788                         res->data.array_data.param_num = minfo->param_num;
11789                         res->data.array_data.num_elem = minfo->count;
11790                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11791                 }
11792                 else {
11793                         res->data.array_data.param_num = -1;
11794                         res->data.array_data.num_elem = -1;
11795                         res->data.array_data.elem_mult = -1;
11796                 }
11797                 break;
11798
11799         case MONO_NATIVE_BYVALTSTR:
11800         case MONO_NATIVE_BYVALARRAY:
11801                 res->data.array_data.num_elem = minfo->count;
11802                 break;
11803
11804         case MONO_NATIVE_CUSTOM:
11805                 if (minfo->marshaltyperef) {
11806                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11807                         if (!is_ok (error)) {
11808                                 image_g_free (image, res);
11809                                 return NULL;
11810                         }
11811                         res->data.custom_data.custom_name =
11812                                 type_get_fully_qualified_name (marshaltyperef);
11813                 }
11814                 if (minfo->mcookie) {
11815                         res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
11816                         if (!is_ok (error)) {
11817                                 image_g_free (image, res);
11818                                 return NULL;
11819                         }
11820                 }
11821                 break;
11822
11823         default:
11824                 break;
11825         }
11826
11827         return res;
11828 }
11829 #endif /* !DISABLE_REFLECTION_EMIT */
11830
11831 MonoReflectionMarshalAsAttribute*
11832 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11833                                                         MonoMarshalSpec *spec, MonoError *error)
11834 {
11835         MonoReflectionType *rt;
11836         MonoReflectionMarshalAsAttribute *minfo;
11837         MonoType *mtype;
11838
11839         mono_error_init (error);
11840         
11841         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11842         if (!minfo)
11843                 return NULL;
11844         minfo->utype = spec->native;
11845
11846         switch (minfo->utype) {
11847         case MONO_NATIVE_LPARRAY:
11848                 minfo->array_subtype = spec->data.array_data.elem_type;
11849                 minfo->size_const = spec->data.array_data.num_elem;
11850                 if (spec->data.array_data.param_num != -1)
11851                         minfo->size_param_index = spec->data.array_data.param_num;
11852                 break;
11853
11854         case MONO_NATIVE_BYVALTSTR:
11855         case MONO_NATIVE_BYVALARRAY:
11856                 minfo->size_const = spec->data.array_data.num_elem;
11857                 break;
11858
11859         case MONO_NATIVE_CUSTOM:
11860                 if (spec->data.custom_data.custom_name) {
11861                         mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11862                         return_val_if_nok  (error, NULL);
11863
11864                         if (mtype) {
11865                                 rt = mono_type_get_object_checked (domain, mtype, error);
11866                                 if (!rt)
11867                                         return NULL;
11868
11869                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11870                         }
11871
11872                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11873                 }
11874                 if (spec->data.custom_data.cookie)
11875                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11876                 break;
11877
11878         default:
11879                 break;
11880         }
11881
11882         return minfo;
11883 }
11884
11885 #ifndef DISABLE_REFLECTION_EMIT
11886 static MonoMethod*
11887 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11888                                          ReflectionMethodBuilder *rmb,
11889                                          MonoMethodSignature *sig,
11890                                          MonoError *error)
11891 {
11892         MonoMethod *m;
11893         MonoMethodWrapper *wrapperm;
11894         MonoMarshalSpec **specs;
11895         MonoReflectionMethodAux *method_aux;
11896         MonoImage *image;
11897         gboolean dynamic;
11898         int i;
11899
11900         mono_error_init (error);
11901         /*
11902          * Methods created using a MethodBuilder should have their memory allocated
11903          * inside the image mempool, while dynamic methods should have their memory
11904          * malloc'd.
11905          */
11906         dynamic = rmb->refs != NULL;
11907         image = dynamic ? NULL : klass->image;
11908
11909         if (!dynamic)
11910                 g_assert (!klass->generic_class);
11911
11912         mono_loader_lock ();
11913
11914         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11915                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11916                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11917         else
11918                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11919
11920         wrapperm = (MonoMethodWrapper*)m;
11921
11922         m->dynamic = dynamic;
11923         m->slot = -1;
11924         m->flags = rmb->attrs;
11925         m->iflags = rmb->iattrs;
11926         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11927         m->klass = klass;
11928         m->signature = sig;
11929         m->sre_method = TRUE;
11930         m->skip_visibility = rmb->skip_visibility;
11931         if (rmb->table_idx)
11932                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11933
11934         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11935                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11936                         m->string_ctor = 1;
11937
11938                 m->signature->pinvoke = 1;
11939         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11940                 m->signature->pinvoke = 1;
11941
11942                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11943
11944                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
11945                 mono_error_assert_ok (error);
11946                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
11947                 mono_error_assert_ok (error);
11948                 
11949                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11950
11951                 if (image_is_dynamic (klass->image))
11952                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11953
11954                 mono_loader_unlock ();
11955
11956                 return m;
11957         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11958                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11959                 MonoMethodHeader *header;
11960                 guint32 code_size;
11961                 gint32 max_stack, i;
11962                 gint32 num_locals = 0;
11963                 gint32 num_clauses = 0;
11964                 guint8 *code;
11965
11966                 if (rmb->ilgen) {
11967                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11968                         code_size = rmb->ilgen->code_len;
11969                         max_stack = rmb->ilgen->max_stack;
11970                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11971                         if (rmb->ilgen->ex_handlers)
11972                                 num_clauses = method_count_clauses (rmb->ilgen);
11973                 } else {
11974                         if (rmb->code) {
11975                                 code = mono_array_addr (rmb->code, guint8, 0);
11976                                 code_size = mono_array_length (rmb->code);
11977                                 /* we probably need to run a verifier on the code... */
11978                                 max_stack = 8; 
11979                         }
11980                         else {
11981                                 code = NULL;
11982                                 code_size = 0;
11983                                 max_stack = 8;
11984                         }
11985                 }
11986
11987                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11988                 header->code_size = code_size;
11989                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11990                 memcpy ((char*)header->code, code, code_size);
11991                 header->max_stack = max_stack;
11992                 header->init_locals = rmb->init_locals;
11993                 header->num_locals = num_locals;
11994
11995                 for (i = 0; i < num_locals; ++i) {
11996                         MonoReflectionLocalBuilder *lb = 
11997                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11998
11999                         header->locals [i] = image_g_new0 (image, MonoType, 1);
12000                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
12001                         mono_error_assert_ok (error);
12002                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
12003                 }
12004
12005                 header->num_clauses = num_clauses;
12006                 if (num_clauses) {
12007                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
12008                                                                  rmb->ilgen, num_clauses, error);
12009                         mono_error_assert_ok (error);
12010                 }
12011
12012                 wrapperm->header = header;
12013         }
12014
12015         if (rmb->generic_params) {
12016                 int count = mono_array_length (rmb->generic_params);
12017                 MonoGenericContainer *container = rmb->generic_container;
12018
12019                 g_assert (container);
12020
12021                 container->type_argc = count;
12022                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
12023                 container->owner.method = m;
12024                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
12025
12026                 m->is_generic = TRUE;
12027                 mono_method_set_generic_container (m, container);
12028
12029                 for (i = 0; i < count; i++) {
12030                         MonoReflectionGenericParam *gp =
12031                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
12032                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
12033                         mono_error_assert_ok (error);
12034                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
12035                         container->type_params [i] = *param;
12036                 }
12037
12038                 /*
12039                  * The method signature might have pointers to generic parameters that belong to other methods.
12040                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
12041                  * generic parameters.
12042                  */
12043                 for (i = 0; i < m->signature->param_count; ++i) {
12044                         MonoType *t = m->signature->params [i];
12045                         if (t->type == MONO_TYPE_MVAR) {
12046                                 MonoGenericParam *gparam =  t->data.generic_param;
12047                                 if (gparam->num < count) {
12048                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
12049                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
12050                                 }
12051
12052                         }
12053                 }
12054
12055                 if (klass->generic_container) {
12056                         container->parent = klass->generic_container;
12057                         container->context.class_inst = klass->generic_container->context.class_inst;
12058                 }
12059                 container->context.method_inst = mono_get_shared_generic_inst (container);
12060         }
12061
12062         if (rmb->refs) {
12063                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
12064                 int i;
12065                 void **data;
12066
12067                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
12068
12069                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
12070                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
12071                 for (i = 0; i < rmb->nrefs; ++i)
12072                         data [i + 1] = rmb->refs [i];
12073         }
12074
12075         method_aux = NULL;
12076
12077         /* Parameter info */
12078         if (rmb->pinfo) {
12079                 if (!method_aux)
12080                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12081                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
12082                 for (i = 0; i <= m->signature->param_count; ++i) {
12083                         MonoReflectionParamBuilder *pb;
12084                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12085                                 if ((i > 0) && (pb->attrs)) {
12086                                         /* Make a copy since it might point to a shared type structure */
12087                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
12088                                         m->signature->params [i - 1]->attrs = pb->attrs;
12089                                 }
12090
12091                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
12092                                         MonoDynamicImage *assembly;
12093                                         guint32 idx, len;
12094                                         MonoTypeEnum def_type;
12095                                         char *p;
12096                                         const char *p2;
12097
12098                                         if (!method_aux->param_defaults) {
12099                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12100                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12101                                         }
12102                                         assembly = (MonoDynamicImage*)klass->image;
12103                                         idx = encode_constant (assembly, pb->def_value, &def_type);
12104                                         /* Copy the data from the blob since it might get realloc-ed */
12105                                         p = assembly->blob.data + idx;
12106                                         len = mono_metadata_decode_blob_size (p, &p2);
12107                                         len += p2 - p;
12108                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12109                                         method_aux->param_default_types [i] = def_type;
12110                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12111                                 }
12112
12113                                 if (pb->name) {
12114                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
12115                                         mono_error_assert_ok (error);
12116                                 }
12117                                 if (pb->cattrs) {
12118                                         if (!method_aux->param_cattr)
12119                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12120                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12121                                 }
12122                         }
12123                 }
12124         }
12125
12126         /* Parameter marshalling */
12127         specs = NULL;
12128         if (rmb->pinfo)         
12129                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12130                         MonoReflectionParamBuilder *pb;
12131                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12132                                 if (pb->marshal_info) {
12133                                         if (specs == NULL)
12134                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12135                                         specs [pb->position] = 
12136                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
12137                                         if (!is_ok (error)) {
12138                                                 mono_loader_unlock ();
12139                                                 image_g_free (image, specs);
12140                                                 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
12141                                                 return NULL;
12142                                         }
12143                                 }
12144                         }
12145                 }
12146         if (specs != NULL) {
12147                 if (!method_aux)
12148                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12149                 method_aux->param_marshall = specs;
12150         }
12151
12152         if (image_is_dynamic (klass->image) && method_aux)
12153                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12154
12155         mono_loader_unlock ();
12156
12157         return m;
12158 }       
12159
12160 static MonoMethod*
12161 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12162 {
12163         ReflectionMethodBuilder rmb;
12164         MonoMethodSignature *sig;
12165
12166         mono_loader_lock ();
12167         g_assert (klass->image != NULL);
12168         sig = ctor_builder_to_signature (klass->image, mb, error);
12169         mono_loader_unlock ();
12170         return_val_if_nok (error, NULL);
12171
12172         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12173                 return NULL;
12174
12175         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12176         return_val_if_nok (error, NULL);
12177         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12178
12179         /* If we are in a generic class, we might be called multiple times from inflate_method */
12180         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12181                 /* ilgen is no longer needed */
12182                 mb->ilgen = NULL;
12183         }
12184
12185         return mb->mhandle;
12186 }
12187
12188 static MonoMethod*
12189 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12190 {
12191         ReflectionMethodBuilder rmb;
12192         MonoMethodSignature *sig;
12193
12194         mono_error_init (error);
12195
12196         mono_loader_lock ();
12197         g_assert (klass->image != NULL);
12198         sig = method_builder_to_signature (klass->image, mb, error);
12199         mono_loader_unlock ();
12200         return_val_if_nok (error, NULL);
12201
12202         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12203                 return NULL;
12204
12205         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12206         return_val_if_nok (error, NULL);
12207         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12208
12209         /* If we are in a generic class, we might be called multiple times from inflate_method */
12210         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12211                 /* ilgen is no longer needed */
12212                 mb->ilgen = NULL;
12213         }
12214         return mb->mhandle;
12215 }
12216
12217 static MonoClassField*
12218 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12219 {
12220         MonoClassField *field;
12221         MonoType *custom;
12222
12223         mono_error_init (error);
12224
12225         field = g_new0 (MonoClassField, 1);
12226
12227         field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12228         mono_error_assert_ok (error);
12229         if (fb->attrs || fb->modreq || fb->modopt) {
12230                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12231                 if (!is_ok (error)) {
12232                         g_free (field);
12233                         return NULL;
12234                 }
12235                 field->type = mono_metadata_type_dup (NULL, type);
12236                 field->type->attrs = fb->attrs;
12237
12238                 g_assert (image_is_dynamic (klass->image));
12239                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12240                 g_free (field->type);
12241                 if (!is_ok (error)) {
12242                         g_free (field);
12243                         return NULL;
12244                 }
12245                 field->type = mono_metadata_type_dup (klass->image, custom);
12246                 g_free (custom);
12247         } else {
12248                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12249                 if (!is_ok (error)) {
12250                         g_free (field);
12251                         return NULL;
12252                 }
12253         }
12254         if (fb->offset != -1)
12255                 field->offset = fb->offset;
12256         field->parent = klass;
12257         mono_save_custom_attrs (klass->image, field, fb->cattrs);
12258
12259         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12260
12261         return field;
12262 }
12263 #endif
12264
12265 /**
12266  * mono_reflection_bind_generic_parameters:
12267  * @type: a managed type object (which should be some kind of generic (instance? definition?))
12268  * @type_args: the number of type arguments to bind
12269  * @types: array of type arguments
12270  * @error: set on error
12271  *
12272  * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12273  * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
12274  */
12275 MonoType*
12276 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12277 {
12278         MonoClass *klass;
12279         MonoReflectionTypeBuilder *tb = NULL;
12280         gboolean is_dynamic = FALSE;
12281         MonoClass *geninst;
12282
12283         mono_error_init (error);
12284         
12285         mono_loader_lock ();
12286
12287         if (is_sre_type_builder (mono_object_class (type))) {
12288                 tb = (MonoReflectionTypeBuilder *) type;
12289
12290                 is_dynamic = TRUE;
12291         } else if (is_sre_generic_instance (mono_object_class (type))) {
12292                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12293                 MonoReflectionType *gtd = rgi->generic_type;
12294
12295                 if (is_sre_type_builder (mono_object_class (gtd))) {
12296                         tb = (MonoReflectionTypeBuilder *)gtd;
12297                         is_dynamic = TRUE;
12298                 }
12299         }
12300
12301         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12302         if (tb && tb->generic_container) {
12303                 if (!mono_reflection_create_generic_class (tb, error)) {
12304                         mono_loader_unlock ();
12305                         return NULL;
12306                 }
12307         }
12308
12309         MonoType *t = mono_reflection_type_get_handle (type, error);
12310         if (!is_ok (error)) {
12311                 mono_loader_unlock ();
12312                 return NULL;
12313         }
12314
12315         klass = mono_class_from_mono_type (t);
12316         if (!klass->generic_container) {
12317                 mono_loader_unlock ();
12318                 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12319                 return NULL;
12320         }
12321
12322         if (klass->wastypebuilder) {
12323                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12324
12325                 is_dynamic = TRUE;
12326         }
12327
12328         mono_loader_unlock ();
12329
12330         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12331
12332         return &geninst->byval_arg;
12333 }
12334
12335 MonoClass*
12336 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12337 {
12338         MonoGenericClass *gclass;
12339         MonoGenericInst *inst;
12340
12341         g_assert (klass->generic_container);
12342
12343         inst = mono_metadata_get_generic_inst (type_argc, types);
12344         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12345
12346         return mono_generic_class_get_class (gclass);
12347 }
12348
12349 static MonoReflectionMethod*
12350 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
12351 {
12352         MonoClass *klass;
12353         MonoMethod *method, *inflated;
12354         MonoMethodInflated *imethod;
12355         MonoGenericContext tmp_context;
12356         MonoGenericInst *ginst;
12357         MonoType **type_argv;
12358         int count, i;
12359
12360         mono_error_init (error);
12361
12362         /*FIXME but this no longer should happen*/
12363         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12364 #ifndef DISABLE_REFLECTION_EMIT
12365                 MonoReflectionMethodBuilder *mb = NULL;
12366                 MonoType *tb;
12367                 MonoClass *klass;
12368
12369                 mb = (MonoReflectionMethodBuilder *) rmethod;
12370                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
12371                 return_val_if_nok (error, NULL);
12372                 klass = mono_class_from_mono_type (tb);
12373
12374                 method = methodbuilder_to_mono_method (klass, mb, error);
12375                 return_val_if_nok (error, NULL);
12376 #else
12377                 g_assert_not_reached ();
12378                 method = NULL;
12379 #endif
12380         } else {
12381                 method = rmethod->method;
12382         }
12383
12384         klass = method->klass;
12385
12386         if (method->is_inflated)
12387                 method = ((MonoMethodInflated *) method)->declaring;
12388
12389         count = mono_method_signature (method)->generic_param_count;
12390         if (count != mono_array_length (types))
12391                 return NULL;
12392
12393         type_argv = g_new0 (MonoType *, count);
12394         for (i = 0; i < count; i++) {
12395                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12396                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
12397                 if (!is_ok (error)) {
12398                         g_free (type_argv);
12399                         return NULL;
12400                 }
12401         }
12402         ginst = mono_metadata_get_generic_inst (count, type_argv);
12403         g_free (type_argv);
12404
12405         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12406         tmp_context.method_inst = ginst;
12407
12408         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
12409         mono_error_assert_ok (error);
12410         imethod = (MonoMethodInflated *) inflated;
12411
12412         /*FIXME but I think this is no longer necessary*/
12413         if (image_is_dynamic (method->klass->image)) {
12414                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12415                 /*
12416                  * This table maps metadata structures representing inflated methods/fields
12417                  * to the reflection objects representing their generic definitions.
12418                  */
12419                 mono_image_lock ((MonoImage*)image);
12420                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12421                 mono_image_unlock ((MonoImage*)image);
12422         }
12423
12424         if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
12425                 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
12426                 return NULL;
12427         }
12428         
12429         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
12430         return ret;
12431 }
12432
12433 MonoReflectionMethod*
12434 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12435 {
12436         MonoError error;
12437         MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
12438         mono_error_set_pending_exception (&error);
12439         return result;
12440 }
12441
12442
12443 #ifndef DISABLE_REFLECTION_EMIT
12444
12445 static MonoMethod *
12446 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12447 {
12448         MonoMethodInflated *imethod;
12449         MonoGenericContext *context;
12450         int i;
12451
12452         /*
12453          * With generic code sharing the klass might not be inflated.
12454          * This can happen because classes inflated with their own
12455          * type arguments are "normalized" to the uninflated class.
12456          */
12457         if (!klass->generic_class)
12458                 return method;
12459
12460         context = mono_class_get_context (klass);
12461
12462         if (klass->method.count && klass->methods) {
12463                 /* Find the already created inflated method */
12464                 for (i = 0; i < klass->method.count; ++i) {
12465                         g_assert (klass->methods [i]->is_inflated);
12466                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12467                                 break;
12468                 }
12469                 g_assert (i < klass->method.count);
12470                 imethod = (MonoMethodInflated*)klass->methods [i];
12471         } else {
12472                 MonoError error;
12473                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12474                 mono_error_assert_ok (&error);
12475         }
12476
12477         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12478                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12479
12480                 mono_image_lock ((MonoImage*)image);
12481                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12482                 mono_image_unlock ((MonoImage*)image);
12483         }
12484         return (MonoMethod *) imethod;
12485 }
12486
12487 static MonoMethod *
12488 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12489 {
12490         MonoMethod *method;
12491         MonoClass *gklass;
12492
12493         mono_error_init (error);
12494
12495         MonoClass *type_class = mono_object_class (type);
12496
12497         if (is_sre_generic_instance (type_class)) {
12498                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12499                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12500                 return_val_if_nok (error, NULL);
12501                 gklass = mono_class_from_mono_type (generic_type);
12502         } else if (is_sre_type_builder (type_class)) {
12503                 MonoType *t = mono_reflection_type_get_handle (type, error);
12504                 return_val_if_nok (error, NULL);
12505                 gklass = mono_class_from_mono_type (t);
12506         } else if (type->type) {
12507                 gklass = mono_class_from_mono_type (type->type);
12508                 gklass = mono_class_get_generic_type_definition (gklass);
12509         } else {
12510                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12511         }
12512
12513         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12514                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12515                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12516                 else {
12517                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12518                         if (!method)
12519                                 return NULL;
12520                 }
12521         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12522                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12523                 if (!method)
12524                         return NULL;
12525         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12526                 method = ((MonoReflectionMethod *) obj)->method;
12527         else {
12528                 method = NULL; /* prevent compiler warning */
12529                 g_error ("can't handle type %s", obj->vtable->klass->name);
12530         }
12531
12532         MonoType *t = mono_reflection_type_get_handle (type, error);
12533         return_val_if_nok (error, NULL);
12534         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12535 }
12536
12537 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12538 static gboolean
12539 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12540 {
12541         MonoGenericClass *gclass;
12542         MonoDynamicGenericClass *dgclass;
12543         MonoClass *klass, *gklass;
12544         MonoType *gtype;
12545         int i;
12546
12547         mono_error_init (error);
12548
12549         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12550         return_val_if_nok (error, FALSE);
12551         klass = mono_class_from_mono_type (gtype);
12552         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12553         gclass = gtype->data.generic_class;
12554
12555         if (!gclass->is_dynamic)
12556                 return TRUE;
12557
12558         dgclass = (MonoDynamicGenericClass *) gclass;
12559
12560         if (dgclass->initialized)
12561                 return TRUE;
12562
12563         gklass = gclass->container_class;
12564         mono_class_init (gklass);
12565
12566         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12567
12568         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12569         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12570         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12571
12572         for (i = 0; i < dgclass->count_fields; i++) {
12573                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12574                 MonoClassField *field, *inflated_field = NULL;
12575
12576                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12577                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12578                         return_val_if_nok (error, FALSE);
12579                 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12580                         field = ((MonoReflectionField *) obj)->field;
12581                 else {
12582                         field = NULL; /* prevent compiler warning */
12583                         g_assert_not_reached ();
12584                 }
12585
12586                 dgclass->fields [i] = *field;
12587                 dgclass->fields [i].parent = klass;
12588                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12589                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12590                 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12591                 dgclass->field_generic_types [i] = field->type;
12592                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12593                 dgclass->field_objects [i] = obj;
12594
12595                 if (inflated_field) {
12596                         g_free (inflated_field);
12597                 } else {
12598                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12599                 }
12600         }
12601
12602         dgclass->initialized = TRUE;
12603         return TRUE;
12604 }
12605
12606 void
12607 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12608 {
12609         MonoError error;
12610         (void) reflection_generic_class_initialize (type, fields, &error);
12611         mono_error_set_pending_exception (&error);
12612 }
12613
12614 void
12615 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12616 {
12617         MonoDynamicGenericClass *dgclass;
12618         int i;
12619
12620         g_assert (gclass->is_dynamic);
12621
12622         dgclass = (MonoDynamicGenericClass *)gclass;
12623
12624         for (i = 0; i < dgclass->count_fields; ++i) {
12625                 MonoClassField *field = dgclass->fields + i;
12626                 mono_metadata_free_type (field->type);
12627                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12628         }
12629 }
12630
12631 /**
12632  * fix_partial_generic_class:
12633  * @klass: a generic instantiation MonoClass
12634  * @error: set on error
12635  *
12636  * Assumes that the generic container of @klass has its vtable
12637  * initialized, and updates the parent class, insterfaces, methods and
12638  * fields of @klass by inflating the types using the generic context.
12639  *
12640  * On success returns TRUE, on failure returns FALSE and sets @error.
12641  *
12642  */
12643 static gboolean
12644 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12645 {
12646         MonoClass *gklass = klass->generic_class->container_class;
12647         MonoDynamicGenericClass *dgclass;
12648         int i;
12649
12650         mono_error_init (error);
12651
12652         if (klass->wastypebuilder)
12653                 return TRUE;
12654
12655         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12656         if (klass->parent != gklass->parent) {
12657                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12658                 if (mono_error_ok (error)) {
12659                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12660                         mono_metadata_free_type (parent_type);
12661                         if (parent != klass->parent) {
12662                                 /*fool mono_class_setup_parent*/
12663                                 klass->supertypes = NULL;
12664                                 mono_class_setup_parent (klass, parent);
12665                         }
12666                 } else {
12667                         if (gklass->wastypebuilder)
12668                                 klass->wastypebuilder = TRUE;
12669                         return FALSE;
12670                 }
12671         }
12672
12673         if (!dgclass->initialized)
12674                 return TRUE;
12675
12676         if (klass->method.count != gklass->method.count) {
12677                 klass->method.count = gklass->method.count;
12678                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12679
12680                 for (i = 0; i < klass->method.count; i++) {
12681                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12682                                 gklass->methods [i], klass, mono_class_get_context (klass), error);
12683                         mono_error_assert_ok (error);
12684                 }
12685         }
12686
12687         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12688                 klass->interface_count = gklass->interface_count;
12689                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12690                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12691
12692                 for (i = 0; i < gklass->interface_count; ++i) {
12693                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12694                         return_val_if_nok (error, FALSE);
12695
12696                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12697                         mono_metadata_free_type (iface_type);
12698
12699                         if (!ensure_runtime_vtable (klass->interfaces [i], error))
12700                                 return FALSE;
12701                 }
12702                 klass->interfaces_inited = 1;
12703         }
12704
12705         if (klass->field.count != gklass->field.count) {
12706                 klass->field.count = gklass->field.count;
12707                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12708
12709                 for (i = 0; i < klass->field.count; i++) {
12710                         klass->fields [i] = gklass->fields [i];
12711                         klass->fields [i].parent = klass;
12712                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12713                         return_val_if_nok (error, FALSE);
12714                 }
12715         }
12716
12717         /*We can only finish with this klass once it's parent has as well*/
12718         if (gklass->wastypebuilder)
12719                 klass->wastypebuilder = TRUE;
12720         return TRUE;
12721 }
12722
12723 /**
12724  * ensure_generic_class_runtime_vtable:
12725  * @klass a generic class
12726  * @error set on error
12727  *
12728  * Ensures that the generic container of @klass has a vtable and
12729  * returns TRUE on success.  On error returns FALSE and sets @error.
12730  */
12731 static gboolean
12732 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12733 {
12734         MonoClass *gklass = klass->generic_class->container_class;
12735
12736         mono_error_init (error);
12737
12738         if (!ensure_runtime_vtable (gklass, error))
12739                 return FALSE;
12740
12741         return fix_partial_generic_class (klass, error);
12742 }
12743
12744 /**
12745  * ensure_runtime_vtable:
12746  * @klass the class
12747  * @error set on error
12748  *
12749  * Ensures that @klass has a vtable and returns TRUE on success. On
12750  * error returns FALSE and sets @error.
12751  */
12752 static gboolean
12753 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12754 {
12755         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12756         int i, num, j;
12757
12758         mono_error_init (error);
12759
12760         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12761                 return TRUE;
12762         if (klass->parent)
12763                 if (!ensure_runtime_vtable (klass->parent, error))
12764                         return FALSE;
12765
12766         if (tb) {
12767                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12768                 num += tb->num_methods;
12769                 klass->method.count = num;
12770                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12771                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12772                 for (i = 0; i < num; ++i) {
12773                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12774                         if (!ctor)
12775                                 return FALSE;
12776                         klass->methods [i] = ctor;
12777                 }
12778                 num = tb->num_methods;
12779                 j = i;
12780                 for (i = 0; i < num; ++i) {
12781                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12782                         if (!meth)
12783                                 return FALSE;
12784                         klass->methods [j++] = meth;
12785                 }
12786         
12787                 if (tb->interfaces) {
12788                         klass->interface_count = mono_array_length (tb->interfaces);
12789                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12790                         for (i = 0; i < klass->interface_count; ++i) {
12791                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12792                                 return_val_if_nok (error, FALSE);
12793                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12794                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12795                                         return FALSE;
12796                         }
12797                         klass->interfaces_inited = 1;
12798                 }
12799         } else if (klass->generic_class){
12800                 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12801                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12802                         return FALSE;
12803                 }
12804         }
12805
12806         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12807                 int slot_num = 0;
12808                 for (i = 0; i < klass->method.count; ++i) {
12809                         MonoMethod *im = klass->methods [i];
12810                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12811                                 im->slot = slot_num++;
12812                 }
12813                 
12814                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12815                 mono_class_setup_interface_offsets (klass);
12816                 mono_class_setup_interface_id (klass);
12817         }
12818
12819         /*
12820          * The generic vtable is needed even if image->run is not set since some
12821          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12822          * method->slot being defined.
12823          */
12824
12825         /* 
12826          * tb->methods could not be freed since it is used for determining 
12827          * overrides during dynamic vtable construction.
12828          */
12829
12830         return TRUE;
12831 }
12832
12833 static MonoMethod*
12834 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12835 {
12836         mono_error_init (error);
12837         MonoClass *klass = mono_object_class (method);
12838         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12839                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12840                 return sr_method->method;
12841         }
12842         if (is_sre_method_builder (klass)) {
12843                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12844                 return mb->mhandle;
12845         }
12846         if (is_sre_method_on_tb_inst (klass)) {
12847                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12848                 MonoMethod *result;
12849                 /*FIXME move this to a proper method and unify with resolve_object*/
12850                 if (m->method_args) {
12851                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12852                 } else {
12853                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12854                         return_val_if_nok (error, NULL);
12855                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12856                         MonoMethod *mono_method;
12857
12858                         if (is_sre_method_builder (mono_object_class (m->mb)))
12859                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12860                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12861                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12862                         else
12863                                 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)));
12864
12865                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12866                 }
12867                 return result;
12868         }
12869
12870         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12871         return NULL;
12872 }
12873
12874 void
12875 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12876 {
12877         MonoReflectionTypeBuilder *tb;
12878         int i, j, onum;
12879         MonoReflectionMethod *m;
12880
12881         mono_error_init (error);
12882         *overrides = NULL;
12883         *num_overrides = 0;
12884
12885         g_assert (image_is_dynamic (klass->image));
12886
12887         if (!mono_class_get_ref_info (klass))
12888                 return;
12889
12890         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12891
12892         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12893
12894         onum = 0;
12895         if (tb->methods) {
12896                 for (i = 0; i < tb->num_methods; ++i) {
12897                         MonoReflectionMethodBuilder *mb = 
12898                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12899                         if (mb->override_methods)
12900                                 onum += mono_array_length (mb->override_methods);
12901                 }
12902         }
12903
12904         if (onum) {
12905                 *overrides = g_new0 (MonoMethod*, onum * 2);
12906
12907                 onum = 0;
12908                 for (i = 0; i < tb->num_methods; ++i) {
12909                         MonoReflectionMethodBuilder *mb = 
12910                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12911                         if (mb->override_methods) {
12912                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12913                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12914
12915                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12916                                         return_if_nok (error);
12917                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12918
12919                                         g_assert (mb->mhandle);
12920
12921                                         onum ++;
12922                                 }
12923                         }
12924                 }
12925         }
12926
12927         *num_overrides = onum;
12928 }
12929
12930 static void
12931 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12932 {
12933         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12934         MonoReflectionFieldBuilder *fb;
12935         MonoClassField *field;
12936         MonoImage *image = klass->image;
12937         const char *p, *p2;
12938         int i;
12939         guint32 len, idx, real_size = 0;
12940
12941         klass->field.count = tb->num_fields;
12942         klass->field.first = 0;
12943
12944         mono_error_init (error);
12945
12946         if (tb->class_size) {
12947                 if ((tb->packing_size & 0xffffff00) != 0) {
12948                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12949                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12950                         return;
12951                 }
12952                 klass->packing_size = tb->packing_size;
12953                 real_size = klass->instance_size + tb->class_size;
12954         }
12955
12956         if (!klass->field.count) {
12957                 klass->instance_size = MAX (klass->instance_size, real_size);
12958                 return;
12959         }
12960         
12961         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12962         mono_class_alloc_ext (klass);
12963         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12964         /*
12965         This is, guess what, a hack.
12966         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12967         On the static path no field class is resolved, only types are built. This is the right thing to do
12968         but we suck.
12969         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12970         */
12971         klass->size_inited = 1;
12972
12973         for (i = 0; i < klass->field.count; ++i) {
12974                 MonoArray *rva_data;
12975                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12976                 field = &klass->fields [i];
12977                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12978                 if (!mono_error_ok (error))
12979                         return;
12980                 if (fb->attrs) {
12981                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12982                         return_if_nok (error);
12983                         field->type = mono_metadata_type_dup (klass->image, type);
12984                         field->type->attrs = fb->attrs;
12985                 } else {
12986                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12987                         return_if_nok (error);
12988                 }
12989
12990                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12991                         char *base = mono_array_addr (rva_data, char, 0);
12992                         size_t size = mono_array_length (rva_data);
12993                         char *data = (char *)mono_image_alloc (klass->image, size);
12994                         memcpy (data, base, size);
12995                         klass->ext->field_def_values [i].data = data;
12996                 }
12997                 if (fb->offset != -1)
12998                         field->offset = fb->offset;
12999                 field->parent = klass;
13000                 fb->handle = field;
13001                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
13002
13003                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
13004                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
13005                 }
13006                 if (fb->def_value) {
13007                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13008                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
13009                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
13010                         /* Copy the data from the blob since it might get realloc-ed */
13011                         p = assembly->blob.data + idx;
13012                         len = mono_metadata_decode_blob_size (p, &p2);
13013                         len += p2 - p;
13014                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
13015                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
13016                 }
13017         }
13018
13019         klass->instance_size = MAX (klass->instance_size, real_size);
13020         mono_class_layout_fields (klass, klass->instance_size);
13021 }
13022
13023 static void
13024 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
13025 {
13026         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13027         MonoReflectionPropertyBuilder *pb;
13028         MonoImage *image = klass->image;
13029         MonoProperty *properties;
13030         int i;
13031
13032         mono_error_init (error);
13033
13034         if (!klass->ext)
13035                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13036
13037         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
13038         klass->ext->property.first = 0;
13039
13040         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
13041         klass->ext->properties = properties;
13042         for (i = 0; i < klass->ext->property.count; ++i) {
13043                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
13044                 properties [i].parent = klass;
13045                 properties [i].attrs = pb->attrs;
13046                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
13047                 if (!mono_error_ok (error))
13048                         return;
13049                 if (pb->get_method)
13050                         properties [i].get = pb->get_method->mhandle;
13051                 if (pb->set_method)
13052                         properties [i].set = pb->set_method->mhandle;
13053
13054                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
13055                 if (pb->def_value) {
13056                         guint32 len, idx;
13057                         const char *p, *p2;
13058                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13059                         if (!klass->ext->prop_def_values)
13060                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
13061                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
13062                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
13063                         /* Copy the data from the blob since it might get realloc-ed */
13064                         p = assembly->blob.data + idx;
13065                         len = mono_metadata_decode_blob_size (p, &p2);
13066                         len += p2 - p;
13067                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
13068                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
13069                 }
13070         }
13071 }
13072
13073 static MonoReflectionEvent *
13074 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
13075 {
13076         mono_error_init (error);
13077
13078         MonoEvent *event = g_new0 (MonoEvent, 1);
13079         MonoClass *klass;
13080
13081         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13082         if (!is_ok (error)) {
13083                 g_free (event);
13084                 return NULL;
13085         }
13086         klass = mono_class_from_mono_type (type);
13087
13088         event->parent = klass;
13089         event->attrs = eb->attrs;
13090         event->name = mono_string_to_utf8_checked (eb->name, error);
13091         if (!is_ok (error)) {
13092                 g_free (event);
13093                 return NULL;
13094         }
13095         if (eb->add_method)
13096                 event->add = eb->add_method->mhandle;
13097         if (eb->remove_method)
13098                 event->remove = eb->remove_method->mhandle;
13099         if (eb->raise_method)
13100                 event->raise = eb->raise_method->mhandle;
13101
13102 #ifndef MONO_SMALL_CONFIG
13103         if (eb->other_methods) {
13104                 int j;
13105                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
13106                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13107                         MonoReflectionMethodBuilder *mb = 
13108                                 mono_array_get (eb->other_methods,
13109                                                 MonoReflectionMethodBuilder*, j);
13110                         event->other [j] = mb->mhandle;
13111                 }
13112         }
13113 #endif
13114
13115         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
13116         if (!is_ok (error)) {
13117 #ifndef MONO_SMALL_CONFIG
13118                 g_free (event->other);
13119 #endif
13120                 g_free (event);
13121                 return NULL;
13122         }
13123         return ev_obj;
13124 }
13125
13126 MonoReflectionEvent *
13127 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13128 {
13129         MonoError error;
13130         MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13131         mono_error_set_pending_exception (&error);
13132         return result;
13133 }
13134
13135 static void
13136 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13137 {
13138         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13139         MonoReflectionEventBuilder *eb;
13140         MonoImage *image = klass->image;
13141         MonoEvent *events;
13142         int i;
13143
13144         mono_error_init (error);
13145
13146         if (!klass->ext)
13147                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13148
13149         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13150         klass->ext->event.first = 0;
13151
13152         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13153         klass->ext->events = events;
13154         for (i = 0; i < klass->ext->event.count; ++i) {
13155                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13156                 events [i].parent = klass;
13157                 events [i].attrs = eb->attrs;
13158                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13159                 if (!mono_error_ok (error))
13160                         return;
13161                 if (eb->add_method)
13162                         events [i].add = eb->add_method->mhandle;
13163                 if (eb->remove_method)
13164                         events [i].remove = eb->remove_method->mhandle;
13165                 if (eb->raise_method)
13166                         events [i].raise = eb->raise_method->mhandle;
13167
13168 #ifndef MONO_SMALL_CONFIG
13169                 if (eb->other_methods) {
13170                         int j;
13171                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13172                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13173                                 MonoReflectionMethodBuilder *mb = 
13174                                         mono_array_get (eb->other_methods,
13175                                                                         MonoReflectionMethodBuilder*, j);
13176                                 events [i].other [j] = mb->mhandle;
13177                         }
13178                 }
13179 #endif
13180                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13181         }
13182 }
13183
13184 struct remove_instantiations_user_data
13185 {
13186         MonoClass *klass;
13187         MonoError *error;
13188 };
13189
13190 static gboolean
13191 remove_instantiations_of_and_ensure_contents (gpointer key,
13192                                                   gpointer value,
13193                                                   gpointer user_data)
13194 {
13195         struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13196         MonoType *type = (MonoType*)key;
13197         MonoClass *klass = data->klass;
13198         gboolean already_failed = !is_ok (data->error);
13199         MonoError lerror;
13200         MonoError *error = already_failed ? &lerror : data->error;
13201
13202         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13203                 MonoClass *inst_klass = mono_class_from_mono_type (type);
13204                 //Ensure it's safe to use it.
13205                 if (!fix_partial_generic_class (inst_klass, error)) {
13206                         mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13207                         // Marked the class with failure, but since some other instantiation already failed,
13208                         // just report that one, and swallow the error from this one.
13209                         if (already_failed)
13210                                 mono_error_cleanup (error);
13211                 }
13212                 return TRUE;
13213         } else
13214                 return FALSE;
13215 }
13216
13217 static void
13218 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13219 {
13220         mono_error_init (error);
13221         int i;
13222
13223         if (!arr)
13224                 return;
13225
13226         for (i = 0; i < mono_array_length (arr); ++i) {
13227                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13228                 if (!mono_error_ok (error))
13229                         break;
13230         }
13231 }
13232
13233 MonoReflectionType*
13234 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13235 {
13236         MonoError error;
13237         MonoClass *klass;
13238         MonoDomain* domain;
13239         MonoReflectionType* res;
13240         int i, j;
13241
13242         mono_error_init (&error);
13243
13244         domain = mono_object_domain (tb);
13245         klass = mono_class_from_mono_type (tb->type.type);
13246
13247         /*
13248          * Check for user defined Type subclasses.
13249          */
13250         RESOLVE_TYPE (tb->parent, &error);
13251         if (!is_ok (&error))
13252                 goto failure_unlocked;
13253         check_array_for_usertypes (tb->interfaces, &error);
13254         if (!is_ok (&error))
13255                 goto failure_unlocked;
13256         if (tb->fields) {
13257                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13258                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13259                         if (fb) {
13260                                 RESOLVE_TYPE (fb->type, &error);
13261                                 if (!is_ok (&error))
13262                                         goto failure_unlocked;
13263                                 check_array_for_usertypes (fb->modreq, &error);
13264                                 if (!is_ok (&error))
13265                                         goto failure_unlocked;
13266                                 check_array_for_usertypes (fb->modopt, &error);
13267                                 if (!is_ok (&error))
13268                                         goto failure_unlocked;
13269                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13270                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13271                                         if (!is_ok (&error))
13272                                                 goto failure_unlocked;
13273                                 }
13274                         }
13275                 }
13276         }
13277         if (tb->methods) {
13278                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13279                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13280                         if (mb) {
13281                                 RESOLVE_TYPE (mb->rtype, &error);
13282                                 if (!is_ok (&error))
13283                                         goto failure_unlocked;
13284                                 check_array_for_usertypes (mb->return_modreq, &error);
13285                                 if (!is_ok (&error))
13286                                         goto failure_unlocked;
13287                                 check_array_for_usertypes (mb->return_modopt, &error);
13288                                 if (!is_ok (&error))
13289                                         goto failure_unlocked;
13290                                 check_array_for_usertypes (mb->parameters, &error);
13291                                 if (!is_ok (&error))
13292                                         goto failure_unlocked;
13293                                 if (mb->param_modreq)
13294                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13295                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13296                                                 if (!is_ok (&error))
13297                                                         goto failure_unlocked;
13298                                         }
13299                                 if (mb->param_modopt)
13300                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13301                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13302                                                 if (!is_ok (&error))
13303                                                         goto failure_unlocked;
13304                                         }
13305                         }
13306                 }
13307         }
13308         if (tb->ctors) {
13309                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13310                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13311                         if (mb) {
13312                                 check_array_for_usertypes (mb->parameters, &error);
13313                                 if (!is_ok (&error))
13314                                         goto failure_unlocked;
13315                                 if (mb->param_modreq)
13316                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13317                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13318                                                 if (!is_ok (&error))
13319                                                         goto failure_unlocked;
13320                                         }
13321                                 if (mb->param_modopt)
13322                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13323                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13324                                                 if (!is_ok (&error))
13325                                                         goto failure_unlocked;
13326                                         }
13327                         }
13328                 }
13329         }
13330
13331         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13332
13333         /* 
13334          * we need to lock the domain because the lock will be taken inside
13335          * So, we need to keep the locking order correct.
13336          */
13337         mono_loader_lock ();
13338         mono_domain_lock (domain);
13339         if (klass->wastypebuilder) {
13340                 mono_domain_unlock (domain);
13341                 mono_loader_unlock ();
13342
13343                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13344                 mono_error_set_pending_exception (&error);
13345
13346                 return res;
13347         }
13348         /*
13349          * Fields to set in klass:
13350          * the various flags: delegate/unicode/contextbound etc.
13351          */
13352         klass->flags = tb->attrs;
13353         klass->has_cctor = 1;
13354
13355         mono_class_setup_parent (klass, klass->parent);
13356         /* fool mono_class_setup_supertypes */
13357         klass->supertypes = NULL;
13358         mono_class_setup_supertypes (klass);
13359         mono_class_setup_mono_type (klass);
13360
13361 #if 0
13362         if (!((MonoDynamicImage*)klass->image)->run) {
13363                 if (klass->generic_container) {
13364                         /* FIXME: The code below can't handle generic classes */
13365                         klass->wastypebuilder = TRUE;
13366                         mono_loader_unlock ();
13367                         mono_domain_unlock (domain);
13368
13369                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13370                         mono_error_set_pending_exception (&error);
13371
13372                         return res;
13373                 }
13374         }
13375 #endif
13376
13377         /* enums are done right away */
13378         if (!klass->enumtype)
13379                 if (!ensure_runtime_vtable (klass, &error))
13380                         goto failure;
13381
13382         if (tb->subtypes) {
13383                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13384                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13385                         mono_class_alloc_ext (klass);
13386                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13387                         if (!is_ok (&error)) goto failure;
13388                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13389                 }
13390         }
13391
13392         klass->nested_classes_inited = TRUE;
13393
13394         /* fields and object layout */
13395         if (klass->parent) {
13396                 if (!klass->parent->size_inited)
13397                         mono_class_init (klass->parent);
13398                 klass->instance_size = klass->parent->instance_size;
13399                 klass->sizes.class_size = 0;
13400                 klass->min_align = klass->parent->min_align;
13401                 /* if the type has no fields we won't call the field_setup
13402                  * routine which sets up klass->has_references.
13403                  */
13404                 klass->has_references |= klass->parent->has_references;
13405         } else {
13406                 klass->instance_size = sizeof (MonoObject);
13407                 klass->min_align = 1;
13408         }
13409
13410         /* FIXME: handle packing_size and instance_size */
13411         typebuilder_setup_fields (klass, &error);
13412         if (!mono_error_ok (&error))
13413                 goto failure;
13414         typebuilder_setup_properties (klass, &error);
13415         if (!mono_error_ok (&error))
13416                 goto failure;
13417
13418         typebuilder_setup_events (klass, &error);
13419         if (!mono_error_ok (&error))
13420                 goto failure;
13421
13422         klass->wastypebuilder = TRUE;
13423
13424         /* 
13425          * If we are a generic TypeBuilder, there might be instantiations in the type cache
13426          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
13427          * we want to return normal System.MonoType objects, so clear these out from the cache.
13428          *
13429          * Together with this we must ensure the contents of all instances to match the created type.
13430          */
13431         if (domain->type_hash && klass->generic_container) {
13432                 struct remove_instantiations_user_data data;
13433                 data.klass = klass;
13434                 data.error = &error;
13435                 mono_error_assert_ok (&error);
13436                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13437                 if (!is_ok (&error))
13438                         goto failure;
13439         }
13440
13441         mono_domain_unlock (domain);
13442         mono_loader_unlock ();
13443
13444         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13445                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13446                 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13447                 goto failure_unlocked;
13448         }
13449
13450         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13451         if (!is_ok (&error))
13452                 goto failure_unlocked;
13453
13454         g_assert (res != (MonoReflectionType*)tb);
13455
13456         return res;
13457
13458 failure:
13459         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13460         klass->wastypebuilder = TRUE;
13461         mono_domain_unlock (domain);
13462         mono_loader_unlock ();
13463 failure_unlocked:
13464         mono_error_set_pending_exception (&error);
13465         return NULL;
13466 }
13467
13468 static gboolean
13469 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13470 {
13471         MonoGenericParamFull *param;
13472         MonoImage *image;
13473         MonoClass *pklass;
13474
13475         mono_error_init (error);
13476
13477         image = &gparam->tbuilder->module->dynamic_image->image;
13478
13479         param = mono_image_new0 (image, MonoGenericParamFull, 1);
13480
13481         param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13482         mono_error_assert_ok (error);
13483         param->param.num = gparam->index;
13484
13485         if (gparam->mbuilder) {
13486                 if (!gparam->mbuilder->generic_container) {
13487                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13488                         return_val_if_nok (error, FALSE);
13489
13490                         MonoClass *klass = mono_class_from_mono_type (tb);
13491                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13492                         gparam->mbuilder->generic_container->is_method = TRUE;
13493                         /* 
13494                          * Cannot set owner.method, since the MonoMethod is not created yet.
13495                          * Set the image field instead, so type_in_image () works.
13496                          */
13497                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
13498                         gparam->mbuilder->generic_container->owner.image = klass->image;
13499                 }
13500                 param->param.owner = gparam->mbuilder->generic_container;
13501         } else if (gparam->tbuilder) {
13502                 if (!gparam->tbuilder->generic_container) {
13503                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13504                         return_val_if_nok (error, FALSE);
13505                         MonoClass *klass = mono_class_from_mono_type (tb);
13506                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13507                         gparam->tbuilder->generic_container->owner.klass = klass;
13508                 }
13509                 param->param.owner = gparam->tbuilder->generic_container;
13510         }
13511
13512         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13513
13514         gparam->type.type = &pklass->byval_arg;
13515
13516         mono_class_set_ref_info (pklass, gparam);
13517         mono_image_append_class_to_reflection_info_set (pklass);
13518
13519         return TRUE;
13520 }
13521
13522 void
13523 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13524 {
13525         MonoError error;
13526         (void) reflection_initialize_generic_parameter (gparam, &error);
13527         mono_error_set_pending_exception (&error);
13528 }
13529
13530
13531 static MonoArray *
13532 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
13533 {
13534         MonoReflectionModuleBuilder *module = sig->module;
13535         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13536         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13537         guint32 buflen, i;
13538         MonoArray *result;
13539         SigBuffer buf;
13540
13541         mono_error_init (error);
13542
13543         check_array_for_usertypes (sig->arguments, error);
13544         return_val_if_nok (error, NULL);
13545
13546         sigbuffer_init (&buf, 32);
13547
13548         sigbuffer_add_value (&buf, 0x07);
13549         sigbuffer_add_value (&buf, na);
13550         if (assembly != NULL){
13551                 for (i = 0; i < na; ++i) {
13552                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13553                         encode_reflection_type (assembly, type, &buf, error);
13554                         if (!is_ok (error)) goto fail;
13555                 }
13556         }
13557
13558         buflen = buf.p - buf.buf;
13559         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13560         if (!is_ok (error)) goto fail;
13561         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13562         sigbuffer_free (&buf);
13563         return result;
13564 fail:
13565         sigbuffer_free (&buf);
13566         return NULL;
13567 }
13568
13569 MonoArray *
13570 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13571 {
13572         MonoError error;
13573         MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
13574         mono_error_set_pending_exception (&error);
13575         return result;
13576 }
13577
13578 static MonoArray *
13579 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
13580 {
13581         MonoDynamicImage *assembly = sig->module->dynamic_image;
13582         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13583         guint32 buflen, i;
13584         MonoArray *result;
13585         SigBuffer buf;
13586
13587         mono_error_init (error);
13588
13589         check_array_for_usertypes (sig->arguments, error);
13590         return_val_if_nok (error, NULL);
13591
13592         sigbuffer_init (&buf, 32);
13593
13594         sigbuffer_add_value (&buf, 0x06);
13595         for (i = 0; i < na; ++i) {
13596                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13597                 encode_reflection_type (assembly, type, &buf, error);
13598                 if (!is_ok (error))
13599                         goto fail;
13600         }
13601
13602         buflen = buf.p - buf.buf;
13603         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13604         if (!is_ok (error)) goto fail;
13605         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13606         sigbuffer_free (&buf);
13607
13608         return result;
13609 fail:
13610         sigbuffer_free (&buf);
13611         return NULL;
13612 }
13613
13614 MonoArray *
13615 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13616 {
13617         MonoError error;
13618         MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
13619         mono_error_set_pending_exception (&error);
13620         return result;
13621 }
13622
13623 typedef struct {
13624         MonoMethod *handle;
13625         MonoDomain *domain;
13626 } DynamicMethodReleaseData;
13627
13628 /*
13629  * The runtime automatically clean up those after finalization.
13630 */      
13631 static MonoReferenceQueue *dynamic_method_queue;
13632
13633 static void
13634 free_dynamic_method (void *dynamic_method)
13635 {
13636         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13637         MonoDomain *domain = data->domain;
13638         MonoMethod *method = data->handle;
13639         guint32 dis_link;
13640
13641         mono_domain_lock (domain);
13642         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13643         g_hash_table_remove (domain->method_to_dyn_method, method);
13644         mono_domain_unlock (domain);
13645         g_assert (dis_link);
13646         mono_gchandle_free (dis_link);
13647
13648         mono_runtime_free_method (domain, method);
13649         g_free (data);
13650 }
13651
13652 static gboolean
13653 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13654 {
13655         MonoReferenceQueue *queue;
13656         MonoMethod *handle;
13657         DynamicMethodReleaseData *release_data;
13658         ReflectionMethodBuilder rmb;
13659         MonoMethodSignature *sig;
13660         MonoClass *klass;
13661         MonoDomain *domain;
13662         GSList *l;
13663         int i;
13664
13665         mono_error_init (error);
13666
13667         if (mono_runtime_is_shutting_down ()) {
13668                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13669                 return FALSE;
13670         }
13671
13672         if (!(queue = dynamic_method_queue)) {
13673                 mono_loader_lock ();
13674                 if (!(queue = dynamic_method_queue))
13675                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13676                 mono_loader_unlock ();
13677         }
13678
13679         sig = dynamic_method_to_signature (mb, error);
13680         return_val_if_nok (error, FALSE);
13681
13682         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13683
13684         /*
13685          * Resolve references.
13686          */
13687         /* 
13688          * Every second entry in the refs array is reserved for storing handle_class,
13689          * which is needed by the ldtoken implementation in the JIT.
13690          */
13691         rmb.nrefs = mb->nrefs;
13692         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13693         for (i = 0; i < mb->nrefs; i += 2) {
13694                 MonoClass *handle_class;
13695                 gpointer ref;
13696                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13697
13698                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13699                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13700                         /*
13701                          * The referenced DynamicMethod should already be created by the managed
13702                          * code, except in the case of circular references. In that case, we store
13703                          * method in the refs array, and fix it up later when the referenced 
13704                          * DynamicMethod is created.
13705                          */
13706                         if (method->mhandle) {
13707                                 ref = method->mhandle;
13708                         } else {
13709                                 /* FIXME: GC object stored in unmanaged memory */
13710                                 ref = method;
13711
13712                                 /* FIXME: GC object stored in unmanaged memory */
13713                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13714                         }
13715                         handle_class = mono_defaults.methodhandle_class;
13716                 } else {
13717                         MonoException *ex = NULL;
13718                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13719                         if (!is_ok  (error)) {
13720                                 g_free (rmb.refs);
13721                                 return FALSE;
13722                         }
13723                         if (!ref)
13724                                 ex = mono_get_exception_type_load (NULL, NULL);
13725                         else if (mono_security_core_clr_enabled ())
13726                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13727
13728                         if (ex) {
13729                                 g_free (rmb.refs);
13730                                 mono_error_set_exception_instance (error, ex);
13731                                 return FALSE;
13732                         }
13733                 }
13734
13735                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13736                 rmb.refs [i + 1] = handle_class;
13737         }               
13738
13739         if (mb->owner) {
13740                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13741                 if (!is_ok (error)) {
13742                         g_free (rmb.refs);
13743                         return FALSE;
13744                 }
13745                 klass = mono_class_from_mono_type (owner_type);
13746         } else {
13747                 klass = mono_defaults.object_class;
13748         }
13749
13750         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
13751         g_free (rmb.refs);
13752         return_val_if_nok (error, FALSE);
13753
13754         release_data = g_new (DynamicMethodReleaseData, 1);
13755         release_data->handle = handle;
13756         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13757         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13758                 g_free (release_data);
13759
13760         /* Fix up refs entries pointing at us */
13761         for (l = mb->referenced_by; l; l = l->next) {
13762                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13763                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13764                 gpointer *data;
13765                 
13766                 g_assert (method->mhandle);
13767
13768                 data = (gpointer*)wrapper->method_data;
13769                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13770                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13771                                 data [i + 1] = mb->mhandle;
13772                 }
13773         }
13774         g_slist_free (mb->referenced_by);
13775
13776         /* ilgen is no longer needed */
13777         mb->ilgen = NULL;
13778
13779         domain = mono_domain_get ();
13780         mono_domain_lock (domain);
13781         if (!domain->method_to_dyn_method)
13782                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13783         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13784         mono_domain_unlock (domain);
13785
13786         return TRUE;
13787 }
13788
13789 void
13790 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13791 {
13792         MonoError error;
13793         (void) reflection_create_dynamic_method (mb, &error);
13794         mono_error_set_pending_exception (&error);
13795 }
13796
13797 #endif /* DISABLE_REFLECTION_EMIT */
13798
13799 /**
13800  * 
13801  * mono_reflection_is_valid_dynamic_token:
13802  * 
13803  * Returns TRUE if token is valid.
13804  * 
13805  */
13806 gboolean
13807 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13808 {
13809         return lookup_dyn_token (image, token) != NULL;
13810 }
13811
13812 MonoMethodSignature *
13813 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13814 {
13815         MonoMethodSignature *sig;
13816         g_assert (image_is_dynamic (image));
13817
13818         mono_error_init (error);
13819
13820         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13821         if (sig)
13822                 return sig;
13823
13824         return mono_method_signature_checked (method, error);
13825 }
13826
13827 #ifndef DISABLE_REFLECTION_EMIT
13828
13829 /**
13830  * mono_reflection_lookup_dynamic_token:
13831  *
13832  * Finish the Builder object pointed to by TOKEN and return the corresponding
13833  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13834  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13835  * mapping table.
13836  *
13837  * LOCKING: Take the loader lock
13838  */
13839 gpointer
13840 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13841 {
13842         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13843         MonoObject *obj;
13844         MonoClass *klass;
13845
13846         mono_error_init (error);
13847         
13848         obj = lookup_dyn_token (assembly, token);
13849         if (!obj) {
13850                 if (valid_token)
13851                         g_error ("Could not find required dynamic token 0x%08x", token);
13852                 else {
13853                         mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13854                         return NULL;
13855                 }
13856         }
13857
13858         if (!handle_class)
13859                 handle_class = &klass;
13860         gpointer result = resolve_object (image, obj, handle_class, context, error);
13861         return result;
13862 }
13863
13864 /*
13865  * ensure_complete_type:
13866  *
13867  *   Ensure that KLASS is completed if it is a dynamic type, or references
13868  * dynamic types.
13869  */
13870 static void
13871 ensure_complete_type (MonoClass *klass, MonoError *error)
13872 {
13873         mono_error_init (error);
13874
13875         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13876                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13877
13878                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13879                 return_if_nok (error);
13880
13881                 // Asserting here could break a lot of code
13882                 //g_assert (klass->wastypebuilder);
13883         }
13884
13885         if (klass->generic_class) {
13886                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13887                 int i;
13888
13889                 for (i = 0; i < inst->type_argc; ++i) {
13890                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13891                         return_if_nok (error);
13892                 }
13893         }
13894 }
13895
13896 static gpointer
13897 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13898 {
13899         gpointer result = NULL;
13900
13901         mono_error_init (error);
13902
13903         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13904                 result = mono_string_intern_checked ((MonoString*)obj, error);
13905                 return_val_if_nok (error, NULL);
13906                 *handle_class = mono_defaults.string_class;
13907                 g_assert (result);
13908         } else if (strcmp (obj->vtable->klass->name, "RuntimeType") == 0) {
13909                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13910                 return_val_if_nok (error, NULL);
13911                 MonoClass *mc = mono_class_from_mono_type (type);
13912                 if (!mono_class_init (mc)) {
13913                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13914                         return NULL;
13915                 }
13916
13917                 if (context) {
13918                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13919                         return_val_if_nok (error, NULL);
13920
13921                         result = mono_class_from_mono_type (inflated);
13922                         mono_metadata_free_type (inflated);
13923                 } else {
13924                         result = mono_class_from_mono_type (type);
13925                 }
13926                 *handle_class = mono_defaults.typehandle_class;
13927                 g_assert (result);
13928         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13929                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13930                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13931                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13932                 result = ((MonoReflectionMethod*)obj)->method;
13933                 if (context) {
13934                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13935                         mono_error_assert_ok (error);
13936                 }
13937                 *handle_class = mono_defaults.methodhandle_class;
13938                 g_assert (result);
13939         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13940                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13941                 result = mb->mhandle;
13942                 if (!result) {
13943                         /* Type is not yet created */
13944                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13945
13946                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13947                         return_val_if_nok (error, NULL);
13948
13949                         /*
13950                          * Hopefully this has been filled in by calling CreateType() on the
13951                          * TypeBuilder.
13952                          */
13953                         /*
13954                          * TODO: This won't work if the application finishes another 
13955                          * TypeBuilder instance instead of this one.
13956                          */
13957                         result = mb->mhandle;
13958                 }
13959                 if (context) {
13960                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13961                         mono_error_assert_ok (error);
13962                 }
13963                 *handle_class = mono_defaults.methodhandle_class;
13964         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13965                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13966
13967                 result = cb->mhandle;
13968                 if (!result) {
13969                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13970
13971                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13972                         return_val_if_nok (error, NULL);
13973                         result = cb->mhandle;
13974                 }
13975                 if (context) {
13976                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13977                         mono_error_assert_ok (error);
13978                 }
13979                 *handle_class = mono_defaults.methodhandle_class;
13980         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13981                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13982
13983                 ensure_complete_type (field->parent, error);
13984                 return_val_if_nok (error, NULL);
13985
13986                 if (context) {
13987                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13988                         return_val_if_nok (error, NULL);
13989
13990                         MonoClass *klass = mono_class_from_mono_type (inflated);
13991                         MonoClassField *inflated_field;
13992                         gpointer iter = NULL;
13993                         mono_metadata_free_type (inflated);
13994                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13995                                 if (!strcmp (field->name, inflated_field->name))
13996                                         break;
13997                         }
13998                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13999                         result = inflated_field;
14000                 } else {
14001                         result = field;
14002                 }
14003                 *handle_class = mono_defaults.fieldhandle_class;
14004                 g_assert (result);
14005         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
14006                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
14007                 result = fb->handle;
14008
14009                 if (!result) {
14010                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
14011
14012                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14013                         return_val_if_nok (error, NULL);
14014                         result = fb->handle;
14015                 }
14016
14017                 if (fb->handle && fb->handle->parent->generic_container) {
14018                         MonoClass *klass = fb->handle->parent;
14019                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
14020                         return_val_if_nok (error, NULL);
14021
14022                         MonoClass *inflated = mono_class_from_mono_type (type);
14023
14024                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
14025                         g_assert (result);
14026                         mono_metadata_free_type (type);
14027                 }
14028                 *handle_class = mono_defaults.fieldhandle_class;
14029         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
14030                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
14031                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
14032                 return_val_if_nok (error, NULL);
14033                 MonoClass *klass;
14034
14035                 klass = type->data.klass;
14036                 if (klass->wastypebuilder) {
14037                         /* Already created */
14038                         result = klass;
14039                 }
14040                 else {
14041                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14042                         return_val_if_nok (error, NULL);
14043                         result = type->data.klass;
14044                         g_assert (result);
14045                 }
14046                 *handle_class = mono_defaults.typehandle_class;
14047         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
14048                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
14049                 MonoMethodSignature *sig;
14050                 int nargs, i;
14051
14052                 if (helper->arguments)
14053                         nargs = mono_array_length (helper->arguments);
14054                 else
14055                         nargs = 0;
14056
14057                 sig = mono_metadata_signature_alloc (image, nargs);
14058                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
14059                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
14060
14061                 if (helper->unmanaged_call_conv) { /* unmanaged */
14062                         sig->call_convention = helper->unmanaged_call_conv - 1;
14063                         sig->pinvoke = TRUE;
14064                 } else if (helper->call_conv & 0x02) {
14065                         sig->call_convention = MONO_CALL_VARARG;
14066                 } else {
14067                         sig->call_convention = MONO_CALL_DEFAULT;
14068                 }
14069
14070                 sig->param_count = nargs;
14071                 /* TODO: Copy type ? */
14072                 sig->ret = helper->return_type->type;
14073                 for (i = 0; i < nargs; ++i) {
14074                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
14075                         if (!is_ok (error)) {
14076                                 image_g_free (image, sig);
14077                                 return NULL;
14078                         }
14079                 }
14080
14081                 result = sig;
14082                 *handle_class = NULL;
14083         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
14084                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
14085                 /* Already created by the managed code */
14086                 g_assert (method->mhandle);
14087                 result = method->mhandle;
14088                 *handle_class = mono_defaults.methodhandle_class;
14089         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
14090                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14091                 return_val_if_nok (error, NULL);
14092                 type = mono_class_inflate_generic_type_checked (type, context, error);
14093                 return_val_if_nok (error, NULL);
14094
14095                 result = mono_class_from_mono_type (type);
14096                 *handle_class = mono_defaults.typehandle_class;
14097                 g_assert (result);
14098                 mono_metadata_free_type (type);
14099         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
14100                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14101                 return_val_if_nok (error, NULL);
14102                 type = mono_class_inflate_generic_type_checked (type, context, error);
14103                 return_val_if_nok (error, NULL);
14104
14105                 result = mono_class_from_mono_type (type);
14106                 *handle_class = mono_defaults.typehandle_class;
14107                 g_assert (result);
14108                 mono_metadata_free_type (type);
14109         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
14110                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
14111                 MonoClass *inflated;
14112                 MonoType *type;
14113                 MonoClassField *field;
14114
14115                 if (is_sre_field_builder (mono_object_class (f->fb)))
14116                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
14117                 else if (is_sr_mono_field (mono_object_class (f->fb)))
14118                         field = ((MonoReflectionField*)f->fb)->field;
14119                 else
14120                         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)));
14121
14122                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
14123                 return_val_if_nok (error, NULL);
14124                 type = mono_class_inflate_generic_type_checked (finst, context, error);
14125                 return_val_if_nok (error, NULL);
14126
14127                 inflated = mono_class_from_mono_type (type);
14128
14129                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
14130                 ensure_complete_type (field->parent, error);
14131                 if (!is_ok (error)) {
14132                         mono_metadata_free_type (type);
14133                         return NULL;
14134                 }
14135
14136                 g_assert (result);
14137                 mono_metadata_free_type (type);
14138                 *handle_class = mono_defaults.fieldhandle_class;
14139         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
14140                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14141                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14142                 return_val_if_nok (error, NULL);
14143                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14144                 return_val_if_nok (error, NULL);
14145
14146                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14147                 MonoMethod *method;
14148
14149                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14150                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14151                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14152                         method = ((MonoReflectionMethod *)c->cb)->method;
14153                 else
14154                         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)));
14155
14156                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14157                 *handle_class = mono_defaults.methodhandle_class;
14158                 mono_metadata_free_type (type);
14159         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14160                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14161                 if (m->method_args) {
14162                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14163                         return_val_if_nok (error, NULL);
14164                         if (context) {
14165                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14166                                 mono_error_assert_ok (error);
14167                         }
14168                 } else {
14169                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14170                         return_val_if_nok (error, NULL);
14171                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14172                         return_val_if_nok (error, NULL);
14173
14174                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
14175                         MonoMethod *method;
14176
14177                         if (is_sre_method_builder (mono_object_class (m->mb)))
14178                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14179                         else if (is_sr_mono_method (mono_object_class (m->mb)))
14180                                 method = ((MonoReflectionMethod *)m->mb)->method;
14181                         else
14182                                 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)));
14183
14184                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14185                         mono_metadata_free_type (type);
14186                 }
14187                 *handle_class = mono_defaults.methodhandle_class;
14188         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14189                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14190                 MonoType *mtype;
14191                 MonoClass *klass;
14192                 MonoMethod *method;
14193                 gpointer iter;
14194                 char *name;
14195
14196                 mtype = mono_reflection_type_get_handle (m->parent, error);
14197                 return_val_if_nok (error, NULL);
14198                 klass = mono_class_from_mono_type (mtype);
14199
14200                 /* Find the method */
14201
14202                 name = mono_string_to_utf8_checked (m->name, error);
14203                 return_val_if_nok (error, NULL);
14204                 iter = NULL;
14205                 while ((method = mono_class_get_methods (klass, &iter))) {
14206                         if (!strcmp (method->name, name))
14207                                 break;
14208                 }
14209                 g_free (name);
14210
14211                 // FIXME:
14212                 g_assert (method);
14213                 // FIXME: Check parameters/return value etc. match
14214
14215                 result = method;
14216                 *handle_class = mono_defaults.methodhandle_class;
14217         } else if (is_sre_array (mono_object_get_class(obj)) ||
14218                                 is_sre_byref (mono_object_get_class(obj)) ||
14219                                 is_sre_pointer (mono_object_get_class(obj))) {
14220                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14221                 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14222                 return_val_if_nok (error, NULL);
14223
14224                 if (context) {
14225                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14226                         return_val_if_nok (error, NULL);
14227
14228                         result = mono_class_from_mono_type (inflated);
14229                         mono_metadata_free_type (inflated);
14230                 } else {
14231                         result = mono_class_from_mono_type (type);
14232                 }
14233                 *handle_class = mono_defaults.typehandle_class;
14234         } else {
14235                 g_print ("%s\n", obj->vtable->klass->name);
14236                 g_assert_not_reached ();
14237         }
14238         return result;
14239 }
14240
14241 #else /* DISABLE_REFLECTION_EMIT */
14242
14243 MonoArray*
14244 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
14245 {
14246         g_assert_not_reached ();
14247         return NULL;
14248 }
14249
14250 void
14251 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14252 {
14253         g_assert_not_reached ();
14254 }
14255
14256 void
14257 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14258 {
14259         g_assert_not_reached ();
14260 }
14261
14262 gboolean
14263 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
14264 {
14265         g_assert_not_reached ();
14266         return FALSE;
14267 }
14268
14269 void
14270 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14271 {
14272         g_assert_not_reached ();
14273 }
14274
14275 void
14276 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14277 {
14278         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14279 }
14280
14281 void
14282 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14283 {
14284         g_assert_not_reached ();
14285 }
14286
14287 void
14288 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14289 {
14290         g_assert_not_reached ();
14291 }
14292
14293 MonoReflectionModule *
14294 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14295 {
14296         g_assert_not_reached ();
14297         return NULL;
14298 }
14299
14300 guint32
14301 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14302 {
14303         g_assert_not_reached ();
14304         return 0;
14305 }
14306
14307 guint32
14308 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14309 {
14310         g_assert_not_reached ();
14311         return 0;
14312 }
14313
14314 guint32
14315 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
14316                          gboolean create_open_instance, gboolean register_token, MonoError *error)
14317 {
14318         g_assert_not_reached ();
14319         return 0;
14320 }
14321
14322 void
14323 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14324 {
14325 }
14326
14327 void
14328 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14329 {
14330         g_assert_not_reached ();
14331 }
14332
14333 void
14334 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14335 {
14336         mono_error_init (error);
14337         *overrides = NULL;
14338         *num_overrides = 0;
14339 }
14340
14341 MonoReflectionEvent *
14342 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14343 {
14344         g_assert_not_reached ();
14345         return NULL;
14346 }
14347
14348 MonoReflectionType*
14349 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14350 {
14351         g_assert_not_reached ();
14352         return NULL;
14353 }
14354
14355 void
14356 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14357 {
14358         g_assert_not_reached ();
14359 }
14360
14361 MonoArray *
14362 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14363 {
14364         g_assert_not_reached ();
14365         return NULL;
14366 }
14367
14368 MonoArray *
14369 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14370 {
14371         g_assert_not_reached ();
14372         return NULL;
14373 }
14374
14375 void 
14376 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14377 {
14378 }
14379
14380 gpointer
14381 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
14382 {
14383         mono_error_init (error);
14384         return NULL;
14385 }
14386
14387 MonoType*
14388 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14389 {
14390         mono_error_init (error);
14391         if (!ref)
14392                 return NULL;
14393         return ref->type;
14394 }
14395
14396 void
14397 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14398 {
14399         g_assert_not_reached ();
14400 }
14401
14402 #endif /* DISABLE_REFLECTION_EMIT */
14403
14404 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14405 const static guint32 declsec_flags_map[] = {
14406         0x00000000,                                     /* empty */
14407         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
14408         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
14409         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
14410         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
14411         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
14412         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
14413         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
14414         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
14415         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
14416         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
14417         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
14418         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
14419         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
14420         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
14421         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
14422         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
14423         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
14424         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
14425 };
14426
14427 /*
14428  * Returns flags that includes all available security action associated to the handle.
14429  * @token: metadata token (either for a class or a method)
14430  * @image: image where resides the metadata.
14431  */
14432 static guint32
14433 mono_declsec_get_flags (MonoImage *image, guint32 token)
14434 {
14435         int index = mono_metadata_declsec_from_index (image, token);
14436         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14437         guint32 result = 0;
14438         guint32 action;
14439         int i;
14440
14441         /* HasSecurity can be present for other, not specially encoded, attributes,
14442            e.g. SuppressUnmanagedCodeSecurityAttribute */
14443         if (index < 0)
14444                 return 0;
14445
14446         for (i = index; i < t->rows; i++) {
14447                 guint32 cols [MONO_DECL_SECURITY_SIZE];
14448
14449                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14450                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14451                         break;
14452
14453                 action = cols [MONO_DECL_SECURITY_ACTION];
14454                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14455                         result |= declsec_flags_map [action];
14456                 } else {
14457                         g_assert_not_reached ();
14458                 }
14459         }
14460         return result;
14461 }
14462
14463 /*
14464  * Get the security actions (in the form of flags) associated with the specified method.
14465  *
14466  * @method: The method for which we want the declarative security flags.
14467  * Return the declarative security flags for the method (only).
14468  *
14469  * Note: To keep MonoMethod size down we do not cache the declarative security flags
14470  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
14471  */
14472 guint32
14473 mono_declsec_flags_from_method (MonoMethod *method)
14474 {
14475         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14476                 /* FIXME: No cache (for the moment) */
14477                 guint32 idx = mono_method_get_index (method);
14478                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14479                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14480                 return mono_declsec_get_flags (method->klass->image, idx);
14481         }
14482         return 0;
14483 }
14484
14485 /*
14486  * Get the security actions (in the form of flags) associated with the specified class.
14487  *
14488  * @klass: The class for which we want the declarative security flags.
14489  * Return the declarative security flags for the class.
14490  *
14491  * Note: We cache the flags inside the MonoClass structure as this will get 
14492  *       called very often (at least for each method).
14493  */
14494 guint32
14495 mono_declsec_flags_from_class (MonoClass *klass)
14496 {
14497         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14498                 if (!klass->ext || !klass->ext->declsec_flags) {
14499                         guint32 idx;
14500
14501                         idx = mono_metadata_token_index (klass->type_token);
14502                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14503                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14504                         mono_loader_lock ();
14505                         mono_class_alloc_ext (klass);
14506                         mono_loader_unlock ();
14507                         /* we cache the flags on classes */
14508                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14509                 }
14510                 return klass->ext->declsec_flags;
14511         }
14512         return 0;
14513 }
14514
14515 /*
14516  * Get the security actions (in the form of flags) associated with the specified assembly.
14517  *
14518  * @assembly: The assembly for which we want the declarative security flags.
14519  * Return the declarative security flags for the assembly.
14520  */
14521 guint32
14522 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14523 {
14524         guint32 idx = 1; /* there is only one assembly */
14525         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14526         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14527         return mono_declsec_get_flags (assembly->image, idx);
14528 }
14529
14530
14531 /*
14532  * Fill actions for the specific index (which may either be an encoded class token or
14533  * an encoded method token) from the metadata image.
14534  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14535  */
14536 static MonoBoolean
14537 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14538         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14539 {
14540         MonoBoolean result = FALSE;
14541         MonoTableInfo *t;
14542         guint32 cols [MONO_DECL_SECURITY_SIZE];
14543         int index = mono_metadata_declsec_from_index (image, token);
14544         int i;
14545
14546         t  = &image->tables [MONO_TABLE_DECLSECURITY];
14547         for (i = index; i < t->rows; i++) {
14548                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14549
14550                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14551                         return result;
14552
14553                 /* if present only replace (class) permissions with method permissions */
14554                 /* if empty accept either class or method permissions */
14555                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14556                         if (!actions->demand.blob) {
14557                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14558                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14559                                 actions->demand.blob = (char*) (blob + 2);
14560                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14561                                 result = TRUE;
14562                         }
14563                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14564                         if (!actions->noncasdemand.blob) {
14565                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14566                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14567                                 actions->noncasdemand.blob = (char*) (blob + 2);
14568                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14569                                 result = TRUE;
14570                         }
14571                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14572                         if (!actions->demandchoice.blob) {
14573                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14574                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14575                                 actions->demandchoice.blob = (char*) (blob + 2);
14576                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14577                                 result = TRUE;
14578                         }
14579                 }
14580         }
14581
14582         return result;
14583 }
14584
14585 static MonoBoolean
14586 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14587         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14588 {
14589         guint32 idx = mono_metadata_token_index (klass->type_token);
14590         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14591         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14592         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14593 }
14594
14595 static MonoBoolean
14596 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14597         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14598 {
14599         guint32 idx = mono_method_get_index (method);
14600         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14601         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14602         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14603 }
14604
14605 /*
14606  * Collect all actions (that requires to generate code in mini) assigned for
14607  * the specified method.
14608  * Note: Don't use the content of actions if the function return FALSE.
14609  */
14610 MonoBoolean
14611 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14612 {
14613         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14614                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14615         MonoBoolean result = FALSE;
14616         guint32 flags;
14617
14618         /* quick exit if no declarative security is present in the metadata */
14619         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14620                 return FALSE;
14621
14622         /* we want the original as the wrapper is "free" of the security informations */
14623         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14624                 method = mono_marshal_method_from_wrapper (method);
14625                 if (!method)
14626                         return FALSE;
14627         }
14628
14629         /* First we look for method-level attributes */
14630         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14631                 mono_class_init (method->klass);
14632                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14633
14634                 result = mono_declsec_get_method_demands_params (method, demands, 
14635                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14636         }
14637
14638         /* Here we use (or create) the class declarative cache to look for demands */
14639         flags = mono_declsec_flags_from_class (method->klass);
14640         if (flags & mask) {
14641                 if (!result) {
14642                         mono_class_init (method->klass);
14643                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14644                 }
14645                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14646                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14647         }
14648
14649         /* The boolean return value is used as a shortcut in case nothing needs to
14650            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14651         return result;
14652 }
14653
14654
14655 /*
14656  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14657  *
14658  * Note: Don't use the content of actions if the function return FALSE.
14659  */
14660 MonoBoolean
14661 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14662 {
14663         MonoBoolean result = FALSE;
14664         guint32 flags;
14665
14666         /* quick exit if no declarative security is present in the metadata */
14667         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14668                 return FALSE;
14669
14670         /* we want the original as the wrapper is "free" of the security informations */
14671         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14672                 method = mono_marshal_method_from_wrapper (method);
14673                 if (!method)
14674                         return FALSE;
14675         }
14676
14677         /* results are independant - zeroize both */
14678         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14679         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14680
14681         /* First we look for method-level attributes */
14682         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14683                 mono_class_init (method->klass);
14684
14685                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14686                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14687         }
14688
14689         /* Here we use (or create) the class declarative cache to look for demands */
14690         flags = mono_declsec_flags_from_class (method->klass);
14691         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14692                 mono_class_init (method->klass);
14693
14694                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14695                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14696         }
14697
14698         return result;
14699 }
14700
14701 /*
14702  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14703  *
14704  * @klass       The inherited class - this is the class that provides the security check (attributes)
14705  * @demans      
14706  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14707  * 
14708  * Note: Don't use the content of actions if the function return FALSE.
14709  */
14710 MonoBoolean
14711 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14712 {
14713         MonoBoolean result = FALSE;
14714         guint32 flags;
14715
14716         /* quick exit if no declarative security is present in the metadata */
14717         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14718                 return FALSE;
14719
14720         /* Here we use (or create) the class declarative cache to look for demands */
14721         flags = mono_declsec_flags_from_class (klass);
14722         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14723                 mono_class_init (klass);
14724                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14725
14726                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14727                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14728         }
14729
14730         return result;
14731 }
14732
14733 /*
14734  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14735  *
14736  * Note: Don't use the content of actions if the function return FALSE.
14737  */
14738 MonoBoolean
14739 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14740 {
14741         /* quick exit if no declarative security is present in the metadata */
14742         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14743                 return FALSE;
14744
14745         /* we want the original as the wrapper is "free" of the security informations */
14746         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14747                 method = mono_marshal_method_from_wrapper (method);
14748                 if (!method)
14749                         return FALSE;
14750         }
14751
14752         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14753                 mono_class_init (method->klass);
14754                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14755
14756                 return mono_declsec_get_method_demands_params (method, demands, 
14757                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14758         }
14759         return FALSE;
14760 }
14761
14762
14763 static MonoBoolean
14764 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14765 {
14766         guint32 cols [MONO_DECL_SECURITY_SIZE];
14767         MonoTableInfo *t;
14768         int i;
14769
14770         int index = mono_metadata_declsec_from_index (image, token);
14771         if (index == -1)
14772                 return FALSE;
14773
14774         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14775         for (i = index; i < t->rows; i++) {
14776                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14777
14778                 /* shortcut - index are ordered */
14779                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14780                         return FALSE;
14781
14782                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14783                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14784                         entry->blob = (char*) (metadata + 2);
14785                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14786                         return TRUE;
14787                 }
14788         }
14789
14790         return FALSE;
14791 }
14792
14793 MonoBoolean
14794 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14795 {
14796         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14797                 guint32 idx = mono_method_get_index (method);
14798                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14799                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14800                 return get_declsec_action (method->klass->image, idx, action, entry);
14801         }
14802         return FALSE;
14803 }
14804
14805 MonoBoolean
14806 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14807 {
14808         /* use cache */
14809         guint32 flags = mono_declsec_flags_from_class (klass);
14810         if (declsec_flags_map [action] & flags) {
14811                 guint32 idx = mono_metadata_token_index (klass->type_token);
14812                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14813                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14814                 return get_declsec_action (klass->image, idx, action, entry);
14815         }
14816         return FALSE;
14817 }
14818
14819 MonoBoolean
14820 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14821 {
14822         guint32 idx = 1; /* there is only one assembly */
14823         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14824         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14825
14826         return get_declsec_action (assembly->image, idx, action, entry);
14827 }
14828
14829 gboolean
14830 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14831 {
14832         MonoObject *res, *exc;
14833         void *params [1];
14834         static MonoMethod *method = NULL;
14835
14836         mono_error_init (error);
14837
14838         if (method == NULL) {
14839                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14840                 g_assert (method);
14841         }
14842
14843         /* 
14844          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14845          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14846          */
14847         g_assert (mono_class_get_ref_info (klass));
14848         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14849
14850         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14851         return_val_if_nok (error, FALSE);
14852
14853         MonoError inner_error;
14854         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &inner_error);
14855
14856         if (exc || !is_ok (&inner_error)) {
14857                 mono_error_cleanup (&inner_error);
14858                 return FALSE;
14859         } else
14860                 return *(MonoBoolean*)mono_object_unbox (res);
14861 }
14862
14863 /**
14864  * mono_reflection_type_get_type:
14865  * @reftype: the System.Type object
14866  *
14867  * Returns the MonoType* associated with the C# System.Type object @reftype.
14868  */
14869 MonoType*
14870 mono_reflection_type_get_type (MonoReflectionType *reftype)
14871 {
14872         g_assert (reftype);
14873
14874         MonoError error;
14875         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14876         mono_error_assert_ok (&error);
14877         return result;
14878 }
14879
14880 /**
14881  * mono_reflection_assembly_get_assembly:
14882  * @refassembly: the System.Reflection.Assembly object
14883  *
14884  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14885  */
14886 MonoAssembly*
14887 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14888 {
14889         g_assert (refassembly);
14890
14891         return refassembly->assembly;
14892 }
14893