Merge pull request #3040 from xmcclure/debugger-step-recursive
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13 #include <config.h>
14 #include "mono/utils/mono-digest.h"
15 #include "mono/utils/mono-membar.h"
16 #include "mono/metadata/reflection-internals.h"
17 #include "mono/metadata/tabledefs.h"
18 #include "mono/metadata/metadata-internals.h"
19 #include <mono/metadata/profiler-private.h>
20 #include "mono/metadata/class-internals.h"
21 #include "mono/metadata/gc-internals.h"
22 #include "mono/metadata/tokentype.h"
23 #include "mono/metadata/domain-internals.h"
24 #include "mono/metadata/opcodes.h"
25 #include "mono/metadata/assembly.h"
26 #include "mono/metadata/object-internals.h"
27 #include <mono/metadata/exception.h>
28 #include <mono/metadata/marshal.h>
29 #include <mono/metadata/security-manager.h>
30 #include <stdio.h>
31 #include <glib.h>
32 #include <errno.h>
33 #include <time.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "image.h"
37 #include "cil-coff.h"
38 #include "mono-endian.h"
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/mempool-internals.h>
41 #include <mono/metadata/security-core-clr.h>
42 #include <mono/metadata/debug-helpers.h>
43 #include <mono/metadata/verify-internals.h>
44 #include <mono/metadata/mono-ptr-array.h>
45 #include <mono/utils/mono-string.h>
46 #include <mono/utils/mono-error-internals.h>
47 #include <mono/utils/checked-build.h>
48
49 static gboolean is_usertype (MonoReflectionType *ref);
50 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
51
52 typedef struct {
53         char *p;
54         char *buf;
55         char *end;
56 } SigBuffer;
57
58 #define TEXT_OFFSET 512
59 #define CLI_H_SIZE 136
60 #define FILE_ALIGN 512
61 #define VIRT_ALIGN 8192
62 #define START_TEXT_RVA  0x00002000
63
64 typedef struct {
65         MonoReflectionILGen *ilgen;
66         MonoReflectionType *rtype;
67         MonoArray *parameters;
68         MonoArray *generic_params;
69         MonoGenericContainer *generic_container;
70         MonoArray *pinfo;
71         MonoArray *opt_types;
72         guint32 attrs;
73         guint32 iattrs;
74         guint32 call_conv;
75         guint32 *table_idx; /* note: it's a pointer */
76         MonoArray *code;
77         MonoObject *type;
78         MonoString *name;
79         MonoBoolean init_locals;
80         MonoBoolean skip_visibility;
81         MonoArray *return_modreq;
82         MonoArray *return_modopt;
83         MonoArray *param_modreq;
84         MonoArray *param_modopt;
85         MonoArray *permissions;
86         MonoMethod *mhandle;
87         guint32 nrefs;
88         gpointer *refs;
89         /* for PInvoke */
90         int charset, extra_flags, native_cc;
91         MonoString *dll, *dllentry;
92 } ReflectionMethodBuilder;
93
94 typedef struct {
95         guint32 owner;
96         MonoReflectionGenericParam *gparam;
97 } GenericParamTableEntry;
98
99 const unsigned char table_sizes [MONO_TABLE_NUM] = {
100         MONO_MODULE_SIZE,
101         MONO_TYPEREF_SIZE,
102         MONO_TYPEDEF_SIZE,
103         0,
104         MONO_FIELD_SIZE,
105         0,
106         MONO_METHOD_SIZE,
107         0,
108         MONO_PARAM_SIZE,
109         MONO_INTERFACEIMPL_SIZE,
110         MONO_MEMBERREF_SIZE,    /* 0x0A */
111         MONO_CONSTANT_SIZE,
112         MONO_CUSTOM_ATTR_SIZE,
113         MONO_FIELD_MARSHAL_SIZE,
114         MONO_DECL_SECURITY_SIZE,
115         MONO_CLASS_LAYOUT_SIZE,
116         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
117         MONO_STAND_ALONE_SIGNATURE_SIZE,
118         MONO_EVENT_MAP_SIZE,
119         0,
120         MONO_EVENT_SIZE,
121         MONO_PROPERTY_MAP_SIZE,
122         0,
123         MONO_PROPERTY_SIZE,
124         MONO_METHOD_SEMA_SIZE,
125         MONO_METHODIMPL_SIZE,
126         MONO_MODULEREF_SIZE,    /* 0x1A */
127         MONO_TYPESPEC_SIZE,
128         MONO_IMPLMAP_SIZE,      
129         MONO_FIELD_RVA_SIZE,
130         0,
131         0,
132         MONO_ASSEMBLY_SIZE,     /* 0x20 */
133         MONO_ASSEMBLY_PROCESSOR_SIZE,
134         MONO_ASSEMBLYOS_SIZE,
135         MONO_ASSEMBLYREF_SIZE,
136         MONO_ASSEMBLYREFPROC_SIZE,
137         MONO_ASSEMBLYREFOS_SIZE,
138         MONO_FILE_SIZE,
139         MONO_EXP_TYPE_SIZE,
140         MONO_MANIFEST_SIZE,
141         MONO_NESTED_CLASS_SIZE,
142
143         MONO_GENERICPARAM_SIZE, /* 0x2A */
144         MONO_METHODSPEC_SIZE,
145         MONO_GENPARCONSTRAINT_SIZE
146
147 };
148
149 #ifndef DISABLE_REFLECTION_EMIT
150 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
151 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
152 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
153 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
154 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
155 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
156 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
157 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
158 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
159 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
160 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
161 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
162 #endif
163
164 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
165 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
166 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
167 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
168 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
169 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
170 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
171 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
172 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
173 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
174 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
175 static gboolean is_sre_array (MonoClass *klass);
176 static gboolean is_sre_byref (MonoClass *klass);
177 static gboolean is_sre_pointer (MonoClass *klass);
178 static gboolean is_sre_type_builder (MonoClass *klass);
179 static gboolean is_sre_method_builder (MonoClass *klass);
180 static gboolean is_sre_ctor_builder (MonoClass *klass);
181 static gboolean is_sre_field_builder (MonoClass *klass);
182 static gboolean is_sr_mono_method (MonoClass *klass);
183 static gboolean is_sr_mono_cmethod (MonoClass *klass);
184 static gboolean is_sr_mono_generic_method (MonoClass *klass);
185 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
186 static gboolean is_sr_mono_field (MonoClass *klass);
187 static gboolean is_sr_mono_property (MonoClass *klass);
188 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
189 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190
191 static gboolean type_is_reference (MonoType *type);
192
193 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
194 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
195 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
196
197 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
198 static void init_type_builder_generics (MonoObject *type, MonoError *error);
199
200 #define RESOLVE_TYPE(type, error) do {                                  \
201         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
202 } while (0)
203 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
204         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
205         __type = mono_reflection_type_resolve_user_types (__type, error); \
206         if (mono_error_ok (error))                                      \
207                 mono_array_set (arr, MonoReflectionType*, index, __type); \
208 } while (0)
209
210 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
211
212 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
213 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
214
215 #if SIZEOF_VOID_P == 4
216 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
217 #else
218 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
219 #endif
220
221 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
222 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
223
224 /* Class lazy loading functions */
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
232 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
233 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
234 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
236 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
237 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
238 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
239 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
240 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
241 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
242 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
243 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
244
245 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
246 static GPtrArray *dynamic_images;
247 static mono_mutex_t dynamic_images_mutex;
248
249 static inline void
250 dynamic_images_lock (void)
251 {
252         mono_os_mutex_lock (&dynamic_images_mutex);
253 }
254
255 static inline void
256 dynamic_images_unlock (void)
257 {
258         mono_os_mutex_unlock (&dynamic_images_mutex);
259 }
260
261 /**
262  * mono_find_dynamic_image_owner:
263  *
264  * Find the dynamic image, if any, which a given pointer is located in the memory of.
265  */
266 MonoImage *
267 mono_find_dynamic_image_owner (void *ptr)
268 {
269         MonoImage *owner = NULL;
270         int i;
271
272         dynamic_images_lock ();
273
274         if (dynamic_images)
275         {
276                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
277                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
278                         if (mono_mempool_contains_addr (image->mempool, ptr))
279                                 owner = image;
280                 }
281         }
282
283         dynamic_images_unlock ();
284
285         return owner;
286 }
287
288 void
289 mono_reflection_init (void)
290 {
291         mono_os_mutex_init (&dynamic_images_mutex);
292 }
293
294 static inline void
295 dynamic_image_lock (MonoDynamicImage *image)
296 {
297         MONO_ENTER_GC_SAFE;
298         mono_image_lock ((MonoImage*)image);
299         MONO_EXIT_GC_SAFE;
300 }
301
302 static inline void
303 dynamic_image_unlock (MonoDynamicImage *image)
304 {
305         mono_image_unlock ((MonoImage*)image);
306 }
307
308 static void
309 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
310 {
311         MONO_REQ_GC_UNSAFE_MODE;
312
313         dynamic_image_lock (assembly);
314         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
315         dynamic_image_unlock (assembly);
316 }
317
318 static MonoObject*
319 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
320 {
321         MONO_REQ_GC_UNSAFE_MODE;
322
323         MonoObject *obj;
324
325         dynamic_image_lock (assembly);
326         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
327         dynamic_image_unlock (assembly);
328
329         return obj;
330 }
331
332 static void
333 sigbuffer_init (SigBuffer *buf, int size)
334 {
335         MONO_REQ_GC_NEUTRAL_MODE;
336
337         buf->buf = (char *)g_malloc (size);
338         buf->p = buf->buf;
339         buf->end = buf->buf + size;
340 }
341
342 static void
343 sigbuffer_make_room (SigBuffer *buf, int size)
344 {
345         MONO_REQ_GC_NEUTRAL_MODE;
346
347         if (buf->end - buf->p < size) {
348                 int new_size = buf->end - buf->buf + size + 32;
349                 char *p = (char *)g_realloc (buf->buf, new_size);
350                 size = buf->p - buf->buf;
351                 buf->buf = p;
352                 buf->p = p + size;
353                 buf->end = buf->buf + new_size;
354         }
355 }
356
357 static void
358 sigbuffer_add_value (SigBuffer *buf, guint32 val)
359 {
360         MONO_REQ_GC_NEUTRAL_MODE;
361
362         sigbuffer_make_room (buf, 6);
363         mono_metadata_encode_value (val, buf->p, &buf->p);
364 }
365
366 static void
367 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
368 {
369         MONO_REQ_GC_NEUTRAL_MODE;
370
371         sigbuffer_make_room (buf, 1);
372         buf->p [0] = val;
373         buf->p++;
374 }
375
376 static void
377 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
378 {
379         MONO_REQ_GC_NEUTRAL_MODE;
380
381         sigbuffer_make_room (buf, size);
382         memcpy (buf->p, p, size);
383         buf->p += size;
384 }
385
386 static void
387 sigbuffer_free (SigBuffer *buf)
388 {
389         MONO_REQ_GC_NEUTRAL_MODE;
390
391         g_free (buf->buf);
392 }
393
394 #ifndef DISABLE_REFLECTION_EMIT
395 /**
396  * mp_g_alloc:
397  *
398  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
399  * from the C heap.
400  */
401 static gpointer
402 image_g_malloc (MonoImage *image, guint size)
403 {
404         MONO_REQ_GC_NEUTRAL_MODE;
405
406         if (image)
407                 return mono_image_alloc (image, size);
408         else
409                 return g_malloc (size);
410 }
411 #endif /* !DISABLE_REFLECTION_EMIT */
412
413 /**
414  * image_g_alloc0:
415  *
416  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
417  * from the C heap.
418  */
419 static gpointer
420 image_g_malloc0 (MonoImage *image, guint size)
421 {
422         MONO_REQ_GC_NEUTRAL_MODE;
423
424         if (image)
425                 return mono_image_alloc0 (image, size);
426         else
427                 return g_malloc0 (size);
428 }
429
430 /**
431  * image_g_free:
432  * @image: a MonoImage
433  * @ptr: pointer
434  *
435  * If @image is NULL, free @ptr, otherwise do nothing.
436  */
437 static void
438 image_g_free (MonoImage *image, gpointer ptr)
439 {
440         if (image == NULL)
441                 g_free (ptr);
442 }
443
444 #ifndef DISABLE_REFLECTION_EMIT
445 static char*
446 image_strdup (MonoImage *image, const char *s)
447 {
448         MONO_REQ_GC_NEUTRAL_MODE;
449
450         if (image)
451                 return mono_image_strdup (image, s);
452         else
453                 return g_strdup (s);
454 }
455 #endif
456
457 #define image_g_new(image,struct_type, n_structs)               \
458     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
459
460 #define image_g_new0(image,struct_type, n_structs)              \
461     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
462
463
464 static void
465 alloc_table (MonoDynamicTable *table, guint nrows)
466 {
467         MONO_REQ_GC_NEUTRAL_MODE;
468
469         table->rows = nrows;
470         g_assert (table->columns);
471         if (nrows + 1 >= table->alloc_rows) {
472                 while (nrows + 1 >= table->alloc_rows) {
473                         if (table->alloc_rows == 0)
474                                 table->alloc_rows = 16;
475                         else
476                                 table->alloc_rows *= 2;
477                 }
478
479                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
480         }
481 }
482
483 static void
484 make_room_in_stream (MonoDynamicStream *stream, int size)
485 {
486         MONO_REQ_GC_NEUTRAL_MODE;
487
488         if (size <= stream->alloc_size)
489                 return;
490         
491         while (stream->alloc_size <= size) {
492                 if (stream->alloc_size < 4096)
493                         stream->alloc_size = 4096;
494                 else
495                         stream->alloc_size *= 2;
496         }
497         
498         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
499 }
500
501 static guint32
502 string_heap_insert (MonoDynamicStream *sh, const char *str)
503 {
504         MONO_REQ_GC_NEUTRAL_MODE;
505
506         guint32 idx;
507         guint32 len;
508         gpointer oldkey, oldval;
509
510         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
511                 return GPOINTER_TO_UINT (oldval);
512
513         len = strlen (str) + 1;
514         idx = sh->index;
515         
516         make_room_in_stream (sh, idx + len);
517
518         /*
519          * We strdup the string even if we already copy them in sh->data
520          * so that the string pointers in the hash remain valid even if
521          * we need to realloc sh->data. We may want to avoid that later.
522          */
523         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
524         memcpy (sh->data + idx, str, len);
525         sh->index += len;
526         return idx;
527 }
528
529 static guint32
530 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
531 {
532         MONO_REQ_GC_UNSAFE_MODE;
533
534         mono_error_init (error);
535         char *name = mono_string_to_utf8_checked (str, error);
536         return_val_if_nok (error, -1);
537         guint32 idx;
538         idx = string_heap_insert (sh, name);
539         g_free (name);
540         return idx;
541 }
542
543 #ifndef DISABLE_REFLECTION_EMIT
544 static void
545 string_heap_init (MonoDynamicStream *sh)
546 {
547         MONO_REQ_GC_NEUTRAL_MODE;
548
549         sh->index = 0;
550         sh->alloc_size = 4096;
551         sh->data = (char *)g_malloc (4096);
552         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
553         string_heap_insert (sh, "");
554 }
555 #endif
556
557 static guint32
558 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
559 {
560         MONO_REQ_GC_NEUTRAL_MODE;
561
562         guint32 idx;
563         
564         make_room_in_stream (stream, stream->index + len);
565         memcpy (stream->data + stream->index, data, len);
566         idx = stream->index;
567         stream->index += len;
568         /* 
569          * align index? Not without adding an additional param that controls it since
570          * we may store a blob value in pieces.
571          */
572         return idx;
573 }
574
575 static guint32
576 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
577 {
578         MONO_REQ_GC_NEUTRAL_MODE;
579
580         guint32 idx;
581         
582         make_room_in_stream (stream, stream->index + len);
583         memset (stream->data + stream->index, 0, len);
584         idx = stream->index;
585         stream->index += len;
586         return idx;
587 }
588
589 static void
590 stream_data_align (MonoDynamicStream *stream)
591 {
592         MONO_REQ_GC_NEUTRAL_MODE;
593
594         char buf [4] = {0};
595         guint32 count = stream->index % 4;
596
597         /* we assume the stream data will be aligned */
598         if (count)
599                 mono_image_add_stream_data (stream, buf, 4 - count);
600 }
601
602 #ifndef DISABLE_REFLECTION_EMIT
603 static int
604 mono_blob_entry_hash (const char* str)
605 {
606         MONO_REQ_GC_NEUTRAL_MODE;
607
608         guint len, h;
609         const char *end;
610         len = mono_metadata_decode_blob_size (str, &str);
611         if (len > 0) {
612                 end = str + len;
613                 h = *str;
614                 for (str += 1; str < end; str++)
615                         h = (h << 5) - h + *str;
616                 return h;
617         } else {
618                 return 0;
619         }
620 }
621
622 static gboolean
623 mono_blob_entry_equal (const char *str1, const char *str2) {
624         MONO_REQ_GC_NEUTRAL_MODE;
625
626         int len, len2;
627         const char *end1;
628         const char *end2;
629         len = mono_metadata_decode_blob_size (str1, &end1);
630         len2 = mono_metadata_decode_blob_size (str2, &end2);
631         if (len != len2)
632                 return 0;
633         return memcmp (end1, end2, len) == 0;
634 }
635 #endif
636 static guint32
637 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
638 {
639         MONO_REQ_GC_NEUTRAL_MODE;
640
641         guint32 idx;
642         char *copy;
643         gpointer oldkey, oldval;
644
645         copy = (char *)g_malloc (s1+s2);
646         memcpy (copy, b1, s1);
647         memcpy (copy + s1, b2, s2);
648         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
649                 g_free (copy);
650                 idx = GPOINTER_TO_UINT (oldval);
651         } else {
652                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
653                 mono_image_add_stream_data (&assembly->blob, b2, s2);
654                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
655         }
656         return idx;
657 }
658
659 static guint32
660 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
661 {
662         MONO_REQ_GC_NEUTRAL_MODE;
663
664         char blob_size [8];
665         char *b = blob_size;
666         guint32 size = buf->p - buf->buf;
667         /* store length */
668         g_assert (size <= (buf->end - buf->buf));
669         mono_metadata_encode_value (size, b, &b);
670         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
671 }
672
673 /*
674  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
675  * dest may be misaligned.
676  */
677 static void
678 swap_with_size (char *dest, const char* val, int len, int nelem) {
679         MONO_REQ_GC_NEUTRAL_MODE;
680 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
681         int elem;
682
683         for (elem = 0; elem < nelem; ++elem) {
684                 switch (len) {
685                 case 1:
686                         *dest = *val;
687                         break;
688                 case 2:
689                         dest [0] = val [1];
690                         dest [1] = val [0];
691                         break;
692                 case 4:
693                         dest [0] = val [3];
694                         dest [1] = val [2];
695                         dest [2] = val [1];
696                         dest [3] = val [0];
697                         break;
698                 case 8:
699                         dest [0] = val [7];
700                         dest [1] = val [6];
701                         dest [2] = val [5];
702                         dest [3] = val [4];
703                         dest [4] = val [3];
704                         dest [5] = val [2];
705                         dest [6] = val [1];
706                         dest [7] = val [0];
707                         break;
708                 default:
709                         g_assert_not_reached ();
710                 }
711                 dest += len;
712                 val += len;
713         }
714 #else
715         memcpy (dest, val, len * nelem);
716 #endif
717 }
718
719 static guint32
720 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
721 {
722         MONO_REQ_GC_UNSAFE_MODE;
723         
724         char blob_size [64];
725         char *b = blob_size;
726         guint32 idx = 0, len;
727
728         len = str->length * 2;
729         mono_metadata_encode_value (len, b, &b);
730 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
731         {
732                 char *swapped = g_malloc (2 * mono_string_length (str));
733                 const char *p = (const char*)mono_string_chars (str);
734
735                 swap_with_size (swapped, p, 2, mono_string_length (str));
736                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
737                 g_free (swapped);
738         }
739 #else
740         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
741 #endif
742         return idx;
743 }
744
745 #ifndef DISABLE_REFLECTION_EMIT
746 static MonoClass *
747 default_class_from_mono_type (MonoType *type)
748 {
749         MONO_REQ_GC_NEUTRAL_MODE;
750
751         switch (type->type) {
752         case MONO_TYPE_OBJECT:
753                 return mono_defaults.object_class;
754         case MONO_TYPE_VOID:
755                 return mono_defaults.void_class;
756         case MONO_TYPE_BOOLEAN:
757                 return mono_defaults.boolean_class;
758         case MONO_TYPE_CHAR:
759                 return mono_defaults.char_class;
760         case MONO_TYPE_I1:
761                 return mono_defaults.sbyte_class;
762         case MONO_TYPE_U1:
763                 return mono_defaults.byte_class;
764         case MONO_TYPE_I2:
765                 return mono_defaults.int16_class;
766         case MONO_TYPE_U2:
767                 return mono_defaults.uint16_class;
768         case MONO_TYPE_I4:
769                 return mono_defaults.int32_class;
770         case MONO_TYPE_U4:
771                 return mono_defaults.uint32_class;
772         case MONO_TYPE_I:
773                 return mono_defaults.int_class;
774         case MONO_TYPE_U:
775                 return mono_defaults.uint_class;
776         case MONO_TYPE_I8:
777                 return mono_defaults.int64_class;
778         case MONO_TYPE_U8:
779                 return mono_defaults.uint64_class;
780         case MONO_TYPE_R4:
781                 return mono_defaults.single_class;
782         case MONO_TYPE_R8:
783                 return mono_defaults.double_class;
784         case MONO_TYPE_STRING:
785                 return mono_defaults.string_class;
786         default:
787                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
788                 g_assert_not_reached ();
789         }
790         
791         return NULL;
792 }
793 #endif
794
795 /*
796  * mono_class_get_ref_info:
797  *
798  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
799  */
800 gpointer
801 mono_class_get_ref_info (MonoClass *klass)
802 {
803         MONO_REQ_GC_UNSAFE_MODE;
804
805         if (klass->ref_info_handle == 0)
806                 return NULL;
807         else
808                 return mono_gchandle_get_target (klass->ref_info_handle);
809 }
810
811 void
812 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
813 {
814         MONO_REQ_GC_UNSAFE_MODE;
815
816         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
817         g_assert (klass->ref_info_handle != 0);
818 }
819
820 void
821 mono_class_free_ref_info (MonoClass *klass)
822 {
823         MONO_REQ_GC_NEUTRAL_MODE;
824
825         if (klass->ref_info_handle) {
826                 mono_gchandle_free (klass->ref_info_handle);
827                 klass->ref_info_handle = 0;
828         }
829 }
830
831 static void
832 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
833 {
834         MONO_REQ_GC_NEUTRAL_MODE;
835
836         int i;
837         MonoGenericInst *class_inst;
838         MonoClass *klass;
839
840         g_assert (gclass);
841
842         class_inst = gclass->context.class_inst;
843
844         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
845         klass = gclass->container_class;
846         sigbuffer_add_value (buf, klass->byval_arg.type);
847         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
848
849         sigbuffer_add_value (buf, class_inst->type_argc);
850         for (i = 0; i < class_inst->type_argc; ++i)
851                 encode_type (assembly, class_inst->type_argv [i], buf);
852
853 }
854
855 static void
856 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
857 {
858         MONO_REQ_GC_NEUTRAL_MODE;
859
860         if (!type) {
861                 g_assert_not_reached ();
862                 return;
863         }
864                 
865         if (type->byref)
866                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
867
868         switch (type->type){
869         case MONO_TYPE_VOID:
870         case MONO_TYPE_BOOLEAN:
871         case MONO_TYPE_CHAR:
872         case MONO_TYPE_I1:
873         case MONO_TYPE_U1:
874         case MONO_TYPE_I2:
875         case MONO_TYPE_U2:
876         case MONO_TYPE_I4:
877         case MONO_TYPE_U4:
878         case MONO_TYPE_I8:
879         case MONO_TYPE_U8:
880         case MONO_TYPE_R4:
881         case MONO_TYPE_R8:
882         case MONO_TYPE_I:
883         case MONO_TYPE_U:
884         case MONO_TYPE_STRING:
885         case MONO_TYPE_OBJECT:
886         case MONO_TYPE_TYPEDBYREF:
887                 sigbuffer_add_value (buf, type->type);
888                 break;
889         case MONO_TYPE_PTR:
890                 sigbuffer_add_value (buf, type->type);
891                 encode_type (assembly, type->data.type, buf);
892                 break;
893         case MONO_TYPE_SZARRAY:
894                 sigbuffer_add_value (buf, type->type);
895                 encode_type (assembly, &type->data.klass->byval_arg, buf);
896                 break;
897         case MONO_TYPE_VALUETYPE:
898         case MONO_TYPE_CLASS: {
899                 MonoClass *k = mono_class_from_mono_type (type);
900
901                 if (k->generic_container) {
902                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
903                         encode_generic_class (assembly, gclass, buf);
904                 } else {
905                         /*
906                          * Make sure we use the correct type.
907                          */
908                         sigbuffer_add_value (buf, k->byval_arg.type);
909                         /*
910                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
911                          * otherwise two typerefs could point to the same type, leading to
912                          * verification errors.
913                          */
914                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
915                 }
916                 break;
917         }
918         case MONO_TYPE_ARRAY:
919                 sigbuffer_add_value (buf, type->type);
920                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
921                 sigbuffer_add_value (buf, type->data.array->rank);
922                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
923                 sigbuffer_add_value (buf, 0);
924                 break;
925         case MONO_TYPE_GENERICINST:
926                 encode_generic_class (assembly, type->data.generic_class, buf);
927                 break;
928         case MONO_TYPE_VAR:
929         case MONO_TYPE_MVAR:
930                 sigbuffer_add_value (buf, type->type);
931                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
932                 break;
933         default:
934                 g_error ("need to encode type %x", type->type);
935         }
936 }
937
938 static void
939 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
940 {
941         MONO_REQ_GC_UNSAFE_MODE;
942
943         mono_error_init (error);
944
945         if (!type) {
946                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
947                 return;
948         }
949
950         MonoType *t = mono_reflection_type_get_handle (type, error);
951         return_if_nok (error);
952         encode_type (assembly, t, buf);
953 }
954
955 static void
956 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
957 {
958         MONO_REQ_GC_UNSAFE_MODE;
959
960         int i;
961
962         mono_error_init (error);
963
964         if (modreq) {
965                 for (i = 0; i < mono_array_length (modreq); ++i) {
966                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
967                         return_if_nok (error);
968                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
969                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
970                 }
971         }
972         if (modopt) {
973                 for (i = 0; i < mono_array_length (modopt); ++i) {
974                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
975                         return_if_nok (error);
976                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
977                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
978                 }
979         }
980 }
981
982 #ifndef DISABLE_REFLECTION_EMIT
983 static guint32
984 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
985 {
986         MONO_REQ_GC_UNSAFE_MODE;
987
988         SigBuffer buf;
989         int i;
990         guint32 nparams =  sig->param_count;
991         guint32 idx;
992
993         if (!assembly->save)
994                 return 0;
995
996         sigbuffer_init (&buf, 32);
997         /*
998          * FIXME: vararg, explicit_this, differenc call_conv values...
999          */
1000         idx = sig->call_convention;
1001         if (sig->hasthis)
1002                 idx |= 0x20; /* hasthis */
1003         if (sig->generic_param_count)
1004                 idx |= 0x10; /* generic */
1005         sigbuffer_add_byte (&buf, idx);
1006         if (sig->generic_param_count)
1007                 sigbuffer_add_value (&buf, sig->generic_param_count);
1008         sigbuffer_add_value (&buf, nparams);
1009         encode_type (assembly, sig->ret, &buf);
1010         for (i = 0; i < nparams; ++i) {
1011                 if (i == sig->sentinelpos)
1012                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1013                 encode_type (assembly, sig->params [i], &buf);
1014         }
1015         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1016         sigbuffer_free (&buf);
1017         return idx;
1018 }
1019 #endif
1020
1021 static guint32
1022 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1023 {
1024         MONO_REQ_GC_UNSAFE_MODE;
1025
1026         mono_error_init (error);
1027
1028         /*
1029          * FIXME: reuse code from method_encode_signature().
1030          */
1031         SigBuffer buf;
1032         int i;
1033         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1034         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1035         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1036         guint32 idx;
1037
1038         sigbuffer_init (&buf, 32);
1039         /* LAMESPEC: all the call conv spec is foobared */
1040         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1041         if (mb->call_conv & 2)
1042                 idx |= 0x5; /* vararg */
1043         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1044                 idx |= 0x20; /* hasthis */
1045         if (ngparams)
1046                 idx |= 0x10; /* generic */
1047         sigbuffer_add_byte (&buf, idx);
1048         if (ngparams)
1049                 sigbuffer_add_value (&buf, ngparams);
1050         sigbuffer_add_value (&buf, nparams + notypes);
1051         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1052         if (!is_ok (error))
1053                 goto leave;
1054         encode_reflection_type (assembly, mb->rtype, &buf, error);
1055         if (!is_ok (error))
1056                 goto leave;
1057         for (i = 0; i < nparams; ++i) {
1058                 MonoArray *modreq = NULL;
1059                 MonoArray *modopt = NULL;
1060                 MonoReflectionType *pt;
1061
1062                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1063                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1064                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1065                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1066                 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1067                 if (!is_ok (error))
1068                         goto leave;
1069                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1070                 encode_reflection_type (assembly, pt, &buf, error);
1071                 if (!is_ok (error))
1072                         goto leave;
1073         }
1074         if (notypes)
1075                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1076         for (i = 0; i < notypes; ++i) {
1077                 MonoReflectionType *pt;
1078
1079                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1080                 encode_reflection_type (assembly, pt, &buf, error);
1081                 if (!is_ok (error))
1082                         goto leave;
1083         }
1084
1085         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1086 leave:
1087         sigbuffer_free (&buf);
1088         return idx;
1089 }
1090
1091 static guint32
1092 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1093 {
1094         MONO_REQ_GC_UNSAFE_MODE;
1095
1096         mono_error_init (error);
1097
1098         MonoDynamicTable *table;
1099         guint32 *values;
1100         guint32 idx, sig_idx;
1101         guint nl = mono_array_length (ilgen->locals);
1102         SigBuffer buf;
1103         int i;
1104
1105         sigbuffer_init (&buf, 32);
1106         sigbuffer_add_value (&buf, 0x07);
1107         sigbuffer_add_value (&buf, nl);
1108         for (i = 0; i < nl; ++i) {
1109                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1110                 
1111                 if (lb->is_pinned)
1112                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1113                 
1114                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1115                 if (!is_ok (error)) {
1116                         sigbuffer_free (&buf);
1117                         return 0;
1118                 }
1119         }
1120         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1121         sigbuffer_free (&buf);
1122
1123         if (assembly->standalonesig_cache == NULL)
1124                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1125         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1126         if (idx)
1127                 return idx;
1128
1129         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1130         idx = table->next_idx ++;
1131         table->rows ++;
1132         alloc_table (table, table->rows);
1133         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1134
1135         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1136
1137         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1138
1139         return idx;
1140 }
1141
1142 static guint32
1143 method_count_clauses (MonoReflectionILGen *ilgen)
1144 {
1145         MONO_REQ_GC_UNSAFE_MODE;
1146
1147         guint32 num_clauses = 0;
1148         int i;
1149
1150         MonoILExceptionInfo *ex_info;
1151         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1152                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1153                 if (ex_info->handlers)
1154                         num_clauses += mono_array_length (ex_info->handlers);
1155                 else
1156                         num_clauses++;
1157         }
1158
1159         return num_clauses;
1160 }
1161
1162 #ifndef DISABLE_REFLECTION_EMIT
1163 static MonoExceptionClause*
1164 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1165 {
1166         MONO_REQ_GC_UNSAFE_MODE;
1167
1168         mono_error_init (error);
1169
1170         MonoExceptionClause *clauses;
1171         MonoExceptionClause *clause;
1172         MonoILExceptionInfo *ex_info;
1173         MonoILExceptionBlock *ex_block;
1174         guint32 finally_start;
1175         int i, j, clause_index;;
1176
1177         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1178
1179         clause_index = 0;
1180         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1181                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1182                 finally_start = ex_info->start + ex_info->len;
1183                 if (!ex_info->handlers)
1184                         continue;
1185                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1186                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1187                         clause = &(clauses [clause_index]);
1188
1189                         clause->flags = ex_block->type;
1190                         clause->try_offset = ex_info->start;
1191
1192                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1193                                 clause->try_len = finally_start - ex_info->start;
1194                         else
1195                                 clause->try_len = ex_info->len;
1196                         clause->handler_offset = ex_block->start;
1197                         clause->handler_len = ex_block->len;
1198                         if (ex_block->extype) {
1199                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1200
1201                                 if (!is_ok (error)) {
1202                                         image_g_free (image, clauses);
1203                                         return NULL;
1204                                 }
1205                                 clause->data.catch_class = mono_class_from_mono_type (extype);
1206                         } else {
1207                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1208                                         clause->data.filter_offset = ex_block->filter_offset;
1209                                 else
1210                                         clause->data.filter_offset = 0;
1211                         }
1212                         finally_start = ex_block->start + ex_block->len;
1213
1214                         clause_index ++;
1215                 }
1216         }
1217
1218         return clauses;
1219 }
1220 #endif /* !DISABLE_REFLECTION_EMIT */
1221
1222 /**
1223  * method_encode_code:
1224  *
1225  * @assembly the assembly
1226  * @mb the managed MethodBuilder
1227  * @error set on error
1228  *
1229  * Note that the return value is not sensible if @error is set.
1230  */
1231 static guint32
1232 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1233 {
1234         MONO_REQ_GC_UNSAFE_MODE;
1235
1236         char flags = 0;
1237         guint32 idx;
1238         guint32 code_size;
1239         gint32 max_stack, i;
1240         gint32 num_locals = 0;
1241         gint32 num_exception = 0;
1242         gint maybe_small;
1243         guint32 fat_flags;
1244         char fat_header [12];
1245         guint32 int_value;
1246         guint16 short_value;
1247         guint32 local_sig = 0;
1248         guint32 header_size = 12;
1249         MonoArray *code;
1250
1251         mono_error_init (error);
1252
1253         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1254                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1255                 return 0;
1256
1257         /*if (mb->name)
1258                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1259         if (mb->ilgen) {
1260                 code = mb->ilgen->code;
1261                 code_size = mb->ilgen->code_len;
1262                 max_stack = mb->ilgen->max_stack;
1263                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1264                 if (mb->ilgen->ex_handlers)
1265                         num_exception = method_count_clauses (mb->ilgen);
1266         } else {
1267                 code = mb->code;
1268                 if (code == NULL){
1269                         MonoError inner_error;
1270                         char *name = mono_string_to_utf8_checked (mb->name, &inner_error);
1271                         if (!is_ok (&inner_error)) {
1272                                 name = g_strdup ("");
1273                                 mono_error_cleanup (&inner_error);
1274                         }
1275                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1276                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1277                         g_free (str);
1278                         g_free (name);
1279                         return 0;
1280                 }
1281
1282                 code_size = mono_array_length (code);
1283                 max_stack = 8; /* we probably need to run a verifier on the code... */
1284         }
1285
1286         stream_data_align (&assembly->code);
1287
1288         /* check for exceptions, maxstack, locals */
1289         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1290         if (maybe_small) {
1291                 if (code_size < 64 && !(code_size & 1)) {
1292                         flags = (code_size << 2) | 0x2;
1293                 } else if (code_size < 32 && (code_size & 1)) {
1294                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1295                 } else {
1296                         goto fat_header;
1297                 }
1298                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1299                 /* add to the fixup todo list */
1300                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1301                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1302                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1303                 return assembly->text_rva + idx;
1304         } 
1305 fat_header:
1306         if (num_locals) {
1307                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1308                 return_val_if_nok (error, 0);
1309         }
1310         /* 
1311          * FIXME: need to set also the header size in fat_flags.
1312          * (and more sects and init locals flags)
1313          */
1314         fat_flags =  0x03;
1315         if (num_exception)
1316                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1317         if (mb->init_locals)
1318                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1319         fat_header [0] = fat_flags;
1320         fat_header [1] = (header_size / 4 ) << 4;
1321         short_value = GUINT16_TO_LE (max_stack);
1322         memcpy (fat_header + 2, &short_value, 2);
1323         int_value = GUINT32_TO_LE (code_size);
1324         memcpy (fat_header + 4, &int_value, 4);
1325         int_value = GUINT32_TO_LE (local_sig);
1326         memcpy (fat_header + 8, &int_value, 4);
1327         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1328         /* add to the fixup todo list */
1329         if (mb->ilgen && mb->ilgen->num_token_fixups)
1330                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1331         
1332         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1333         if (num_exception) {
1334                 unsigned char sheader [4];
1335                 MonoILExceptionInfo * ex_info;
1336                 MonoILExceptionBlock * ex_block;
1337                 int j;
1338
1339                 stream_data_align (&assembly->code);
1340                 /* always use fat format for now */
1341                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1342                 num_exception *= 6 * sizeof (guint32);
1343                 num_exception += 4; /* include the size of the header */
1344                 sheader [1] = num_exception & 0xff;
1345                 sheader [2] = (num_exception >> 8) & 0xff;
1346                 sheader [3] = (num_exception >> 16) & 0xff;
1347                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1348                 /* fat header, so we are already aligned */
1349                 /* reverse order */
1350                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1351                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1352                         if (ex_info->handlers) {
1353                                 int finally_start = ex_info->start + ex_info->len;
1354                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1355                                         guint32 val;
1356                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1357                                         /* the flags */
1358                                         val = GUINT32_TO_LE (ex_block->type);
1359                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1360                                         /* try offset */
1361                                         val = GUINT32_TO_LE (ex_info->start);
1362                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1363                                         /* need fault, too, probably */
1364                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1365                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1366                                         else
1367                                                 val = GUINT32_TO_LE (ex_info->len);
1368                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1369                                         /* handler offset */
1370                                         val = GUINT32_TO_LE (ex_block->start);
1371                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1372                                         /* handler len */
1373                                         val = GUINT32_TO_LE (ex_block->len);
1374                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1375                                         finally_start = ex_block->start + ex_block->len;
1376                                         if (ex_block->extype) {
1377                                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1378                                                 return_val_if_nok (error, 0);
1379
1380                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1381                                         } else {
1382                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1383                                                         val = ex_block->filter_offset;
1384                                                 else
1385                                                         val = 0;
1386                                         }
1387                                         val = GUINT32_TO_LE (val);
1388                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1389                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1390                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1391                                 }
1392                         } else {
1393                                 g_error ("No clauses for ex info block %d", i);
1394                         }
1395                 }
1396         }
1397         return assembly->text_rva + idx;
1398 }
1399
1400 static guint32
1401 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1402 {
1403         MONO_REQ_GC_NEUTRAL_MODE;
1404
1405         int i;
1406         MonoDynamicTable *table;
1407         guint32 *values;
1408         
1409         table = &assembly->tables [table_idx];
1410
1411         g_assert (col < table->columns);
1412
1413         values = table->values + table->columns;
1414         for (i = 1; i <= table->rows; ++i) {
1415                 if (values [col] == token)
1416                         return i;
1417                 values += table->columns;
1418         }
1419         return 0;
1420 }
1421
1422 /*
1423  * LOCKING: Acquires the loader lock. 
1424  */
1425 static MonoCustomAttrInfo*
1426 lookup_custom_attr (MonoImage *image, gpointer member)
1427 {
1428         MONO_REQ_GC_NEUTRAL_MODE;
1429
1430         MonoCustomAttrInfo* res;
1431
1432         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1433
1434         if (!res)
1435                 return NULL;
1436
1437         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1438         res->cached = 0;
1439         return res;
1440 }
1441
1442 static gboolean
1443 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1444 {
1445         MONO_REQ_GC_UNSAFE_MODE;
1446
1447         /* FIXME: Need to do more checks */
1448         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1449                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1450
1451                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1452                         return FALSE;
1453         }
1454
1455         return TRUE;
1456 }
1457
1458 static MonoCustomAttrInfo*
1459 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1460 {
1461         MONO_REQ_GC_UNSAFE_MODE;
1462
1463         int i, index, count, not_visible;
1464         MonoCustomAttrInfo *ainfo;
1465         MonoReflectionCustomAttr *cattr;
1466
1467         if (!cattrs)
1468                 return NULL;
1469         /* FIXME: check in assembly the Run flag is set */
1470
1471         count = mono_array_length (cattrs);
1472
1473         /* Skip nonpublic attributes since MS.NET seems to do the same */
1474         /* FIXME: This needs to be done more globally */
1475         not_visible = 0;
1476         for (i = 0; i < count; ++i) {
1477                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1478                 if (!custom_attr_visible (image, cattr))
1479                         not_visible ++;
1480         }
1481         count -= not_visible;
1482
1483         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1484
1485         ainfo->image = image;
1486         ainfo->num_attrs = count;
1487         ainfo->cached = alloc_img != NULL;
1488         index = 0;
1489         for (i = 0; i < count; ++i) {
1490                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1491                 if (custom_attr_visible (image, cattr)) {
1492                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1493                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1494                         ainfo->attrs [index].ctor = cattr->ctor->method;
1495                         ainfo->attrs [index].data = saved;
1496                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1497                         index ++;
1498                 }
1499         }
1500
1501         return ainfo;
1502 }
1503
1504 #ifndef DISABLE_REFLECTION_EMIT
1505 /*
1506  * LOCKING: Acquires the loader lock. 
1507  */
1508 static void
1509 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1510 {
1511         MONO_REQ_GC_UNSAFE_MODE;
1512
1513         MonoCustomAttrInfo *ainfo, *tmp;
1514
1515         if (!cattrs || !mono_array_length (cattrs))
1516                 return;
1517
1518         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1519
1520         mono_loader_lock ();
1521         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1522         if (tmp)
1523                 mono_custom_attrs_free (tmp);
1524         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1525         mono_loader_unlock ();
1526
1527 }
1528 #endif
1529
1530 void
1531 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1532 {
1533         MONO_REQ_GC_NEUTRAL_MODE;
1534
1535         if (ainfo && !ainfo->cached)
1536                 g_free (ainfo);
1537 }
1538
1539 /*
1540  * idx is the table index of the object
1541  * type is one of MONO_CUSTOM_ATTR_*
1542  */
1543 static gboolean
1544 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1545 {
1546         MONO_REQ_GC_UNSAFE_MODE;
1547
1548         MonoDynamicTable *table;
1549         MonoReflectionCustomAttr *cattr;
1550         guint32 *values;
1551         guint32 count, i, token;
1552         char blob_size [6];
1553         char *p = blob_size;
1554         
1555         mono_error_init (error);
1556
1557         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1558         if (!cattrs)
1559                 return TRUE;
1560         count = mono_array_length (cattrs);
1561         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1562         table->rows += count;
1563         alloc_table (table, table->rows);
1564         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1565         idx <<= MONO_CUSTOM_ATTR_BITS;
1566         idx |= type;
1567         for (i = 0; i < count; ++i) {
1568                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1569                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1570                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1571                 if (!mono_error_ok (error)) goto fail;
1572                 type = mono_metadata_token_index (token);
1573                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1574                 switch (mono_metadata_token_table (token)) {
1575                 case MONO_TABLE_METHOD:
1576                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1577                         /*
1578                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1579                          * method, not the one returned by mono_image_create_token ().
1580                          */
1581                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1582                         break;
1583                 case MONO_TABLE_MEMBERREF:
1584                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1585                         break;
1586                 default:
1587                         g_warning ("got wrong token in custom attr");
1588                         continue;
1589                 }
1590                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1591                 p = blob_size;
1592                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1593                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1594                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1595                 values += MONO_CUSTOM_ATTR_SIZE;
1596                 ++table->next_idx;
1597         }
1598
1599         return TRUE;
1600
1601 fail:
1602         return FALSE;
1603 }
1604
1605 static void
1606 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1607 {
1608         MONO_REQ_GC_UNSAFE_MODE;
1609
1610         MonoDynamicTable *table;
1611         guint32 *values;
1612         guint32 count, i, idx;
1613         MonoReflectionPermissionSet *perm;
1614
1615         if (!permissions)
1616                 return;
1617
1618         count = mono_array_length (permissions);
1619         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1620         table->rows += count;
1621         alloc_table (table, table->rows);
1622
1623         for (i = 0; i < mono_array_length (permissions); ++i) {
1624                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1625
1626                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1627
1628                 idx = mono_metadata_token_index (parent_token);
1629                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1630                 switch (mono_metadata_token_table (parent_token)) {
1631                 case MONO_TABLE_TYPEDEF:
1632                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1633                         break;
1634                 case MONO_TABLE_METHOD:
1635                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1636                         break;
1637                 case MONO_TABLE_ASSEMBLY:
1638                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1639                         break;
1640                 default:
1641                         g_assert_not_reached ();
1642                 }
1643
1644                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1645                 values [MONO_DECL_SECURITY_PARENT] = idx;
1646                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1647
1648                 ++table->next_idx;
1649         }
1650 }
1651
1652 /*
1653  * Fill in the MethodDef and ParamDef tables for a method.
1654  * This is used for both normal methods and constructors.
1655  */
1656 static gboolean
1657 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1658 {
1659         MONO_REQ_GC_UNSAFE_MODE;
1660
1661         MonoDynamicTable *table;
1662         guint32 *values;
1663         guint i, count;
1664
1665         mono_error_init (error);
1666
1667         /* room in this table is already allocated */
1668         table = &assembly->tables [MONO_TABLE_METHOD];
1669         *mb->table_idx = table->next_idx ++;
1670         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1671         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1672         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
1673         return_val_if_nok (error, FALSE);
1674         values [MONO_METHOD_FLAGS] = mb->attrs;
1675         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1676         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1677         return_val_if_nok (error, FALSE);
1678         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1679         return_val_if_nok (error, FALSE);
1680
1681         table = &assembly->tables [MONO_TABLE_PARAM];
1682         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1683
1684         mono_image_add_decl_security (assembly, 
1685                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1686
1687         if (mb->pinfo) {
1688                 MonoDynamicTable *mtable;
1689                 guint32 *mvalues;
1690                 
1691                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1692                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1693                 
1694                 count = 0;
1695                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1696                         if (mono_array_get (mb->pinfo, gpointer, i))
1697                                 count++;
1698                 }
1699                 table->rows += count;
1700                 alloc_table (table, table->rows);
1701                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1702                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1703                         MonoReflectionParamBuilder *pb;
1704                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1705                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1706                                 values [MONO_PARAM_SEQUENCE] = i;
1707                                 if (pb->name != NULL) {
1708                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
1709                                         return_val_if_nok (error, FALSE);
1710                                 } else {
1711                                         values [MONO_PARAM_NAME] = 0;
1712                                 }
1713                                 values += MONO_PARAM_SIZE;
1714                                 if (pb->marshal_info) {
1715                                         mtable->rows++;
1716                                         alloc_table (mtable, mtable->rows);
1717                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1718                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1719                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1720                                         return_val_if_nok (error, FALSE);
1721                                 }
1722                                 pb->table_idx = table->next_idx++;
1723                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1724                                         guint32 field_type = 0;
1725                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1726                                         mtable->rows ++;
1727                                         alloc_table (mtable, mtable->rows);
1728                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1729                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1730                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1731                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1732                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1733                                 }
1734                         }
1735                 }
1736         }
1737
1738         return TRUE;
1739 }
1740
1741 #ifndef DISABLE_REFLECTION_EMIT
1742 static gboolean
1743 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1744 {
1745         MONO_REQ_GC_UNSAFE_MODE;
1746
1747         mono_error_init (error);
1748         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1749
1750         rmb->ilgen = mb->ilgen;
1751         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1752         return_val_if_nok (error, FALSE);
1753         rmb->parameters = mb->parameters;
1754         rmb->generic_params = mb->generic_params;
1755         rmb->generic_container = mb->generic_container;
1756         rmb->opt_types = NULL;
1757         rmb->pinfo = mb->pinfo;
1758         rmb->attrs = mb->attrs;
1759         rmb->iattrs = mb->iattrs;
1760         rmb->call_conv = mb->call_conv;
1761         rmb->code = mb->code;
1762         rmb->type = mb->type;
1763         rmb->name = mb->name;
1764         rmb->table_idx = &mb->table_idx;
1765         rmb->init_locals = mb->init_locals;
1766         rmb->skip_visibility = FALSE;
1767         rmb->return_modreq = mb->return_modreq;
1768         rmb->return_modopt = mb->return_modopt;
1769         rmb->param_modreq = mb->param_modreq;
1770         rmb->param_modopt = mb->param_modopt;
1771         rmb->permissions = mb->permissions;
1772         rmb->mhandle = mb->mhandle;
1773         rmb->nrefs = 0;
1774         rmb->refs = NULL;
1775
1776         if (mb->dll) {
1777                 rmb->charset = mb->charset;
1778                 rmb->extra_flags = mb->extra_flags;
1779                 rmb->native_cc = mb->native_cc;
1780                 rmb->dllentry = mb->dllentry;
1781                 rmb->dll = mb->dll;
1782         }
1783
1784         return TRUE;
1785 }
1786
1787 static gboolean
1788 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1789 {
1790         MONO_REQ_GC_UNSAFE_MODE;
1791
1792         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1793
1794         mono_error_init (error);
1795
1796         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1797
1798         rmb->ilgen = mb->ilgen;
1799         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1800         return_val_if_nok (error, FALSE);
1801         rmb->parameters = mb->parameters;
1802         rmb->generic_params = NULL;
1803         rmb->generic_container = NULL;
1804         rmb->opt_types = NULL;
1805         rmb->pinfo = mb->pinfo;
1806         rmb->attrs = mb->attrs;
1807         rmb->iattrs = mb->iattrs;
1808         rmb->call_conv = mb->call_conv;
1809         rmb->code = NULL;
1810         rmb->type = mb->type;
1811         rmb->name = mono_string_new (mono_domain_get (), name);
1812         rmb->table_idx = &mb->table_idx;
1813         rmb->init_locals = mb->init_locals;
1814         rmb->skip_visibility = FALSE;
1815         rmb->return_modreq = NULL;
1816         rmb->return_modopt = NULL;
1817         rmb->param_modreq = mb->param_modreq;
1818         rmb->param_modopt = mb->param_modopt;
1819         rmb->permissions = mb->permissions;
1820         rmb->mhandle = mb->mhandle;
1821         rmb->nrefs = 0;
1822         rmb->refs = NULL;
1823
1824         return TRUE;
1825 }
1826
1827 static void
1828 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1829 {
1830         MONO_REQ_GC_UNSAFE_MODE;
1831
1832         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1833
1834         rmb->ilgen = mb->ilgen;
1835         rmb->rtype = mb->rtype;
1836         rmb->parameters = mb->parameters;
1837         rmb->generic_params = NULL;
1838         rmb->generic_container = NULL;
1839         rmb->opt_types = NULL;
1840         rmb->pinfo = NULL;
1841         rmb->attrs = mb->attrs;
1842         rmb->iattrs = 0;
1843         rmb->call_conv = mb->call_conv;
1844         rmb->code = NULL;
1845         rmb->type = (MonoObject *) mb->owner;
1846         rmb->name = mb->name;
1847         rmb->table_idx = NULL;
1848         rmb->init_locals = mb->init_locals;
1849         rmb->skip_visibility = mb->skip_visibility;
1850         rmb->return_modreq = NULL;
1851         rmb->return_modopt = NULL;
1852         rmb->param_modreq = NULL;
1853         rmb->param_modopt = NULL;
1854         rmb->permissions = NULL;
1855         rmb->mhandle = mb->mhandle;
1856         rmb->nrefs = 0;
1857         rmb->refs = NULL;
1858 }       
1859 #endif
1860
1861 static gboolean
1862 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1863 {
1864         MONO_REQ_GC_UNSAFE_MODE;
1865
1866         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1867         MonoDynamicTable *table;
1868         guint32 *values;
1869         guint32 tok;
1870         MonoReflectionMethod *m;
1871         int i;
1872
1873         mono_error_init (error);
1874
1875         if (!mb->override_methods)
1876                 return TRUE;
1877
1878         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1879                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1880
1881                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1882                 table->rows ++;
1883                 alloc_table (table, table->rows);
1884                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1885                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1886                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1887
1888                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1889                 return_val_if_nok (error, FALSE);
1890
1891                 switch (mono_metadata_token_table (tok)) {
1892                 case MONO_TABLE_MEMBERREF:
1893                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1894                         break;
1895                 case MONO_TABLE_METHOD:
1896                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1897                         break;
1898                 default:
1899                         g_assert_not_reached ();
1900                 }
1901                 values [MONO_METHODIMPL_DECLARATION] = tok;
1902         }
1903
1904         return TRUE;
1905 }
1906
1907 #ifndef DISABLE_REFLECTION_EMIT
1908 static gboolean
1909 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1910 {
1911         MONO_REQ_GC_UNSAFE_MODE;
1912
1913         MonoDynamicTable *table;
1914         guint32 *values;
1915         ReflectionMethodBuilder rmb;
1916         int i;
1917
1918         mono_error_init (error);
1919
1920         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1921             !mono_image_basic_method (&rmb, assembly, error))
1922                 return FALSE;
1923
1924         mb->table_idx = *rmb.table_idx;
1925
1926         if (mb->dll) { /* It's a P/Invoke method */
1927                 guint32 moduleref;
1928                 /* map CharSet values to on-disk values */
1929                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1930                 int extra_flags = mb->extra_flags;
1931                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1932                 table->rows ++;
1933                 alloc_table (table, table->rows);
1934                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1935                 
1936                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1937                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1938                 if (mb->dllentry) {
1939                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry, error);
1940                         return_val_if_nok (error, FALSE);
1941                 } else {
1942                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name, error);
1943                         return_val_if_nok (error, FALSE);
1944                 }
1945                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll, error);
1946                 return_val_if_nok (error, FALSE);
1947                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1948                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1949                         table->rows ++;
1950                         alloc_table (table, table->rows);
1951                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1952                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1953                 }
1954         }
1955
1956         if (mb->generic_params) {
1957                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1958                 table->rows += mono_array_length (mb->generic_params);
1959                 alloc_table (table, table->rows);
1960                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1961                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1962
1963                         mono_image_get_generic_param_info (
1964                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1965                 }
1966         }
1967
1968         return TRUE;
1969 }
1970
1971 static gboolean
1972 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1973 {
1974         MONO_REQ_GC_UNSAFE_MODE;
1975
1976         ReflectionMethodBuilder rmb;
1977
1978         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1979                 return FALSE;
1980
1981         if (!mono_image_basic_method (&rmb, assembly, error))
1982                 return FALSE;
1983
1984         mb->table_idx = *rmb.table_idx;
1985
1986         return TRUE;
1987 }
1988 #endif
1989
1990 static char*
1991 type_get_fully_qualified_name (MonoType *type)
1992 {
1993         MONO_REQ_GC_NEUTRAL_MODE;
1994
1995         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1996 }
1997
1998 static char*
1999 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
2000 {
2001         MONO_REQ_GC_UNSAFE_MODE;
2002
2003         MonoClass *klass;
2004         MonoAssembly *ta;
2005
2006         klass = mono_class_from_mono_type (type);
2007         if (!klass) 
2008                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2009         ta = klass->image->assembly;
2010         if (assembly_is_dynamic (ta) || (ta == ass)) {
2011                 if (klass->generic_class || klass->generic_container)
2012                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
2013                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2014                 else
2015                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2016         }
2017
2018         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2019 }
2020
2021 #ifndef DISABLE_REFLECTION_EMIT
2022 /*field_image is the image to which the eventual custom mods have been encoded against*/
2023 static guint32
2024 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2025 {
2026         MONO_REQ_GC_NEUTRAL_MODE;
2027
2028         SigBuffer buf;
2029         guint32 idx, i, token;
2030
2031         if (!assembly->save)
2032                 return 0;
2033
2034         sigbuffer_init (&buf, 32);
2035         
2036         sigbuffer_add_value (&buf, 0x06);
2037         /* encode custom attributes before the type */
2038         if (type->num_mods) {
2039                 for (i = 0; i < type->num_mods; ++i) {
2040                         if (field_image) {
2041                                 MonoError error;
2042                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2043                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2044
2045                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2046                         } else {
2047                                 token = type->modifiers [i].token;
2048                         }
2049
2050                         if (type->modifiers [i].required)
2051                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2052                         else
2053                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2054
2055                         sigbuffer_add_value (&buf, token);
2056                 }
2057         }
2058         encode_type (assembly, type, &buf);
2059         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2060         sigbuffer_free (&buf);
2061         return idx;
2062 }
2063 #endif
2064
2065 static guint32
2066 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2067 {
2068         MONO_REQ_GC_UNSAFE_MODE;
2069
2070         mono_error_init (error);
2071
2072         SigBuffer buf;
2073         guint32 idx;
2074         guint32 typespec = 0;
2075         MonoType *type;
2076         MonoClass *klass;
2077
2078         init_type_builder_generics (fb->type, error);
2079         return_val_if_nok (error, 0);
2080
2081         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2082         return_val_if_nok (error, 0);
2083         klass = mono_class_from_mono_type (type);
2084
2085         sigbuffer_init (&buf, 32);
2086         
2087         sigbuffer_add_value (&buf, 0x06);
2088         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2089         if (!is_ok (error))
2090                 goto fail;
2091         /* encode custom attributes before the type */
2092
2093         if (klass->generic_container)
2094                 typespec = create_typespec (assembly, type);
2095
2096         if (typespec) {
2097                 MonoGenericClass *gclass;
2098                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2099                 encode_generic_class (assembly, gclass, &buf);
2100         } else {
2101                 encode_type (assembly, type, &buf);
2102         }
2103         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2104         sigbuffer_free (&buf);
2105         return idx;
2106 fail:
2107         sigbuffer_free (&buf);
2108         return 0;
2109 }
2110
2111 static guint32
2112 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2113 {
2114         MONO_REQ_GC_UNSAFE_MODE;
2115
2116         char blob_size [64];
2117         char *b = blob_size;
2118         char *box_val;
2119         char* buf;
2120         guint32 idx = 0, len = 0, dummy = 0;
2121
2122         buf = (char *)g_malloc (64);
2123         if (!val) {
2124                 *ret_type = MONO_TYPE_CLASS;
2125                 len = 4;
2126                 box_val = (char*)&dummy;
2127         } else {
2128                 box_val = ((char*)val) + sizeof (MonoObject);
2129                 *ret_type = val->vtable->klass->byval_arg.type;
2130         }
2131 handle_enum:
2132         switch (*ret_type) {
2133         case MONO_TYPE_BOOLEAN:
2134         case MONO_TYPE_U1:
2135         case MONO_TYPE_I1:
2136                 len = 1;
2137                 break;
2138         case MONO_TYPE_CHAR:
2139         case MONO_TYPE_U2:
2140         case MONO_TYPE_I2:
2141                 len = 2;
2142                 break;
2143         case MONO_TYPE_U4:
2144         case MONO_TYPE_I4:
2145         case MONO_TYPE_R4:
2146                 len = 4;
2147                 break;
2148         case MONO_TYPE_U8:
2149         case MONO_TYPE_I8:
2150                 len = 8;
2151                 break;
2152         case MONO_TYPE_R8:
2153                 len = 8;
2154                 break;
2155         case MONO_TYPE_VALUETYPE: {
2156                 MonoClass *klass = val->vtable->klass;
2157                 
2158                 if (klass->enumtype) {
2159                         *ret_type = mono_class_enum_basetype (klass)->type;
2160                         goto handle_enum;
2161                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2162                         len = 8;
2163                 } else 
2164                         g_error ("we can't encode valuetypes, we should have never reached this line");
2165                 break;
2166         }
2167         case MONO_TYPE_CLASS:
2168                 break;
2169         case MONO_TYPE_STRING: {
2170                 MonoString *str = (MonoString*)val;
2171                 /* there is no signature */
2172                 len = str->length * 2;
2173                 mono_metadata_encode_value (len, b, &b);
2174 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2175                 {
2176                         char *swapped = g_malloc (2 * mono_string_length (str));
2177                         const char *p = (const char*)mono_string_chars (str);
2178
2179                         swap_with_size (swapped, p, 2, mono_string_length (str));
2180                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2181                         g_free (swapped);
2182                 }
2183 #else
2184                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2185 #endif
2186
2187                 g_free (buf);
2188                 return idx;
2189         }
2190         case MONO_TYPE_GENERICINST:
2191                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2192                 goto handle_enum;
2193         default:
2194                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2195         }
2196
2197         /* there is no signature */
2198         mono_metadata_encode_value (len, b, &b);
2199 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2200         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2201         swap_with_size (blob_size, box_val, len, 1);
2202         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2203 #else
2204         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2205 #endif
2206
2207         g_free (buf);
2208         return idx;
2209 }
2210
2211 static guint32
2212 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2213 {
2214         MONO_REQ_GC_UNSAFE_MODE;
2215
2216         mono_error_init (error);
2217
2218         char *str;
2219         SigBuffer buf;
2220         guint32 idx, len;
2221
2222         sigbuffer_init (&buf, 32);
2223
2224         sigbuffer_add_value (&buf, minfo->type);
2225
2226         switch (minfo->type) {
2227         case MONO_NATIVE_BYVALTSTR:
2228         case MONO_NATIVE_BYVALARRAY:
2229                 sigbuffer_add_value (&buf, minfo->count);
2230                 break;
2231         case MONO_NATIVE_LPARRAY:
2232                 if (minfo->eltype || minfo->has_size) {
2233                         sigbuffer_add_value (&buf, minfo->eltype);
2234                         if (minfo->has_size) {
2235                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2236                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2237
2238                                 /* LAMESPEC: ElemMult is undocumented */
2239                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2240                         }
2241                 }
2242                 break;
2243         case MONO_NATIVE_SAFEARRAY:
2244                 if (minfo->eltype)
2245                         sigbuffer_add_value (&buf, minfo->eltype);
2246                 break;
2247         case MONO_NATIVE_CUSTOM:
2248                 if (minfo->guid) {
2249                         str = mono_string_to_utf8_checked (minfo->guid, error);
2250                         if (!is_ok (error)) {
2251                                 sigbuffer_free (&buf);
2252                                 return 0;
2253                         }
2254                         len = strlen (str);
2255                         sigbuffer_add_value (&buf, len);
2256                         sigbuffer_add_mem (&buf, str, len);
2257                         g_free (str);
2258                 } else {
2259                         sigbuffer_add_value (&buf, 0);
2260                 }
2261                 /* native type name */
2262                 sigbuffer_add_value (&buf, 0);
2263                 /* custom marshaler type name */
2264                 if (minfo->marshaltype || minfo->marshaltyperef) {
2265                         if (minfo->marshaltyperef) {
2266                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2267                                 if (!is_ok (error)) {
2268                                         sigbuffer_free (&buf);
2269                                         return 0;
2270                                 }
2271                                 str = type_get_fully_qualified_name (marshaltype);
2272                         } else {
2273                                 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
2274                                 if (!is_ok (error)) {
2275                                         sigbuffer_free (&buf);
2276                                         return 0;
2277                                 }
2278                         }
2279                         len = strlen (str);
2280                         sigbuffer_add_value (&buf, len);
2281                         sigbuffer_add_mem (&buf, str, len);
2282                         g_free (str);
2283                 } else {
2284                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2285                         sigbuffer_add_value (&buf, 0);
2286                 }
2287                 if (minfo->mcookie) {
2288                         str = mono_string_to_utf8_checked (minfo->mcookie, error);
2289                         if (!is_ok (error)) {
2290                                 sigbuffer_free (&buf);
2291                                 return 0;
2292                         }
2293                         len = strlen (str);
2294                         sigbuffer_add_value (&buf, len);
2295                         sigbuffer_add_mem (&buf, str, len);
2296                         g_free (str);
2297                 } else {
2298                         sigbuffer_add_value (&buf, 0);
2299                 }
2300                 break;
2301         default:
2302                 break;
2303         }
2304         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2305         sigbuffer_free (&buf);
2306         return idx;
2307 }
2308
2309 static void
2310 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2311 {
2312         MONO_REQ_GC_UNSAFE_MODE;
2313
2314         mono_error_init (error);
2315
2316         MonoDynamicTable *table;
2317         guint32 *values;
2318
2319         /* maybe this fixup should be done in the C# code */
2320         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2321                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2322         table = &assembly->tables [MONO_TABLE_FIELD];
2323         fb->table_idx = table->next_idx ++;
2324         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2325         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2326         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name, error);
2327         return_if_nok (error);
2328         values [MONO_FIELD_FLAGS] = fb->attrs;
2329         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2330         return_if_nok (error);
2331
2332
2333         if (fb->offset != -1) {
2334                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2335                 table->rows ++;
2336                 alloc_table (table, table->rows);
2337                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2338                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2339                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2340         }
2341         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2342                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2343                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2344                 table->rows ++;
2345                 alloc_table (table, table->rows);
2346                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2347                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2348                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2349                 values [MONO_CONSTANT_TYPE] = field_type;
2350                 values [MONO_CONSTANT_PADDING] = 0;
2351         }
2352         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2353                 guint32 rva_idx;
2354                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2355                 table->rows ++;
2356                 alloc_table (table, table->rows);
2357                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2358                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2359                 /*
2360                  * We store it in the code section because it's simpler for now.
2361                  */
2362                 if (fb->rva_data) {
2363                         if (mono_array_length (fb->rva_data) >= 10)
2364                                 stream_data_align (&assembly->code);
2365                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2366                 } else
2367                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2368                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2369         }
2370         if (fb->marshal_info) {
2371                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2372                 table->rows ++;
2373                 alloc_table (table, table->rows);
2374                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2375                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2376                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2377                 return_if_nok (error);
2378         }
2379 }
2380
2381 static guint32
2382 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2383 {
2384         MONO_REQ_GC_UNSAFE_MODE;
2385
2386         mono_error_init (error);
2387
2388         SigBuffer buf;
2389         guint32 nparams = 0;
2390         MonoReflectionMethodBuilder *mb = fb->get_method;
2391         MonoReflectionMethodBuilder *smb = fb->set_method;
2392         guint32 idx, i;
2393
2394         if (mb && mb->parameters)
2395                 nparams = mono_array_length (mb->parameters);
2396         if (!mb && smb && smb->parameters)
2397                 nparams = mono_array_length (smb->parameters) - 1;
2398         sigbuffer_init (&buf, 32);
2399         if (fb->call_conv & 0x20)
2400                 sigbuffer_add_byte (&buf, 0x28);
2401         else
2402                 sigbuffer_add_byte (&buf, 0x08);
2403         sigbuffer_add_value (&buf, nparams);
2404         if (mb) {
2405                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2406                 if (!is_ok (error))
2407                         goto fail;
2408                 for (i = 0; i < nparams; ++i) {
2409                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2410                         encode_reflection_type (assembly, pt, &buf, error);
2411                         if (!is_ok (error))
2412                                 goto fail;
2413                 }
2414         } else if (smb && smb->parameters) {
2415                 /* the property type is the last param */
2416                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2417                 if (!is_ok (error))
2418                         goto fail;
2419
2420                 for (i = 0; i < nparams; ++i) {
2421                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2422                         encode_reflection_type (assembly, pt, &buf, error);
2423                         if (!is_ok (error))
2424                                 goto fail;
2425                 }
2426         } else {
2427                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2428                 if (!is_ok (error))
2429                         goto fail;
2430         }
2431
2432         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2433         sigbuffer_free (&buf);
2434         return idx;
2435 fail:
2436         sigbuffer_free (&buf);
2437         return 0;
2438 }
2439
2440 static void
2441 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2442 {
2443         MONO_REQ_GC_UNSAFE_MODE;
2444
2445         mono_error_init (error);
2446
2447         MonoDynamicTable *table;
2448         guint32 *values;
2449         guint num_methods = 0;
2450         guint32 semaidx;
2451
2452         /* 
2453          * we need to set things in the following tables:
2454          * PROPERTYMAP (info already filled in _get_type_info ())
2455          * PROPERTY    (rows already preallocated in _get_type_info ())
2456          * METHOD      (method info already done with the generic method code)
2457          * METHODSEMANTICS
2458          * CONSTANT
2459          */
2460         table = &assembly->tables [MONO_TABLE_PROPERTY];
2461         pb->table_idx = table->next_idx ++;
2462         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2463         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name, error);
2464         return_if_nok (error);
2465         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2466         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2467         return_if_nok (error);
2468
2469
2470         /* FIXME: we still don't handle 'other' methods */
2471         if (pb->get_method) num_methods ++;
2472         if (pb->set_method) num_methods ++;
2473
2474         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2475         table->rows += num_methods;
2476         alloc_table (table, table->rows);
2477
2478         if (pb->get_method) {
2479                 semaidx = table->next_idx ++;
2480                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2481                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2482                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2483                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2484         }
2485         if (pb->set_method) {
2486                 semaidx = table->next_idx ++;
2487                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2488                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2489                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2490                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2491         }
2492         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2493                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2494                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2495                 table->rows ++;
2496                 alloc_table (table, table->rows);
2497                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2498                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2499                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2500                 values [MONO_CONSTANT_TYPE] = field_type;
2501                 values [MONO_CONSTANT_PADDING] = 0;
2502         }
2503 }
2504
2505 static void
2506 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2507 {
2508         MONO_REQ_GC_UNSAFE_MODE;
2509
2510         MonoDynamicTable *table;
2511         guint32 *values;
2512         guint num_methods = 0;
2513         guint32 semaidx;
2514
2515         /* 
2516          * we need to set things in the following tables:
2517          * EVENTMAP (info already filled in _get_type_info ())
2518          * EVENT    (rows already preallocated in _get_type_info ())
2519          * METHOD      (method info already done with the generic method code)
2520          * METHODSEMANTICS
2521          */
2522         table = &assembly->tables [MONO_TABLE_EVENT];
2523         eb->table_idx = table->next_idx ++;
2524         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2525         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name, error);
2526         return_if_nok (error);
2527         values [MONO_EVENT_FLAGS] = eb->attrs;
2528         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2529         return_if_nok (error);
2530         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2531
2532         /*
2533          * FIXME: we still don't handle 'other' methods 
2534          */
2535         if (eb->add_method) num_methods ++;
2536         if (eb->remove_method) num_methods ++;
2537         if (eb->raise_method) num_methods ++;
2538
2539         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2540         table->rows += num_methods;
2541         alloc_table (table, table->rows);
2542
2543         if (eb->add_method) {
2544                 semaidx = table->next_idx ++;
2545                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2546                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2547                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2548                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2549         }
2550         if (eb->remove_method) {
2551                 semaidx = table->next_idx ++;
2552                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2553                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2554                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2555                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2556         }
2557         if (eb->raise_method) {
2558                 semaidx = table->next_idx ++;
2559                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2560                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2561                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2562                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2563         }
2564 }
2565
2566 static void
2567 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2568 {
2569         MONO_REQ_GC_UNSAFE_MODE;
2570
2571         mono_error_init (error);
2572
2573         MonoDynamicTable *table;
2574         guint32 num_constraints, i;
2575         guint32 *values;
2576         guint32 table_idx;
2577
2578         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2579         num_constraints = gparam->iface_constraints ?
2580                 mono_array_length (gparam->iface_constraints) : 0;
2581         table->rows += num_constraints;
2582         if (gparam->base_type)
2583                 table->rows++;
2584         alloc_table (table, table->rows);
2585
2586         if (gparam->base_type) {
2587                 table_idx = table->next_idx ++;
2588                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2589
2590                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2591                 return_if_nok (error);
2592                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2593                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2594         }
2595
2596         for (i = 0; i < num_constraints; i++) {
2597                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2598                         gparam->iface_constraints, gpointer, i);
2599
2600                 table_idx = table->next_idx ++;
2601                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2602
2603                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2604                 return_if_nok (error);
2605
2606                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2607                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2608         }
2609 }
2610
2611 static void
2612 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2613 {
2614         MONO_REQ_GC_UNSAFE_MODE;
2615
2616         GenericParamTableEntry *entry;
2617
2618         /*
2619          * The GenericParam table must be sorted according to the `owner' field.
2620          * We need to do this sorting prior to writing the GenericParamConstraint
2621          * table, since we have to use the final GenericParam table indices there
2622          * and they must also be sorted.
2623          */
2624
2625         entry = g_new0 (GenericParamTableEntry, 1);
2626         entry->owner = owner;
2627         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2628         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2629         entry->gparam = gparam;
2630         
2631         g_ptr_array_add (assembly->gen_params, entry);
2632 }
2633
2634 static gboolean
2635 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2636 {
2637         MONO_REQ_GC_UNSAFE_MODE;
2638
2639         MonoDynamicTable *table;
2640         MonoGenericParam *param;
2641         guint32 *values;
2642         guint32 table_idx;
2643
2644         mono_error_init (error);
2645
2646         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2647         table_idx = table->next_idx ++;
2648         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2649
2650         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2651         return_val_if_nok (error, FALSE);
2652
2653         param = gparam_type->data.generic_param;
2654
2655         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2656         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2657         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2658         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2659
2660         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2661                 return FALSE;
2662
2663         encode_constraints (entry->gparam, table_idx, assembly, error);
2664         return_val_if_nok (error, FALSE);
2665
2666         return TRUE;
2667 }
2668
2669 static guint32
2670 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2671 {
2672         MONO_REQ_GC_UNSAFE_MODE;
2673
2674         MonoDynamicTable *table;
2675         guint32 token;
2676         guint32 *values;
2677         guint32 cols [MONO_ASSEMBLY_SIZE];
2678         const char *pubkey;
2679         guint32 publen;
2680
2681         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2682                 return token;
2683
2684         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2685                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2686                 token = table->next_idx ++;
2687                 table->rows ++;
2688                 alloc_table (table, table->rows);
2689                 values = table->values + token * MONO_MODULEREF_SIZE;
2690                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2691
2692                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2693                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2694                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2695
2696                 return token;
2697         }
2698         
2699         if (assembly_is_dynamic (image->assembly))
2700                 /* FIXME: */
2701                 memset (cols, 0, sizeof (cols));
2702         else {
2703                 /* image->assembly->image is the manifest module */
2704                 image = image->assembly->image;
2705                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2706         }
2707
2708         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2709         token = table->next_idx ++;
2710         table->rows ++;
2711         alloc_table (table, table->rows);
2712         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2713         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2714         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2715         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2716         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2717         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2718         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2719         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2720         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2721
2722         if (strcmp ("", image->assembly->aname.culture)) {
2723                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2724                                 image->assembly->aname.culture);
2725         }
2726
2727         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2728                 guchar pubtoken [9];
2729                 pubtoken [0] = 8;
2730                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2731                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2732         } else {
2733                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2734         }
2735         token <<= MONO_RESOLUTION_SCOPE_BITS;
2736         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2737         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2738         return token;
2739 }
2740
2741 static guint32
2742 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2743 {
2744         MONO_REQ_GC_NEUTRAL_MODE;
2745
2746         MonoDynamicTable *table;
2747         guint32 *values;
2748         guint32 token;
2749         SigBuffer buf;
2750
2751         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2752                 return token;
2753
2754         sigbuffer_init (&buf, 32);
2755         switch (type->type) {
2756         case MONO_TYPE_FNPTR:
2757         case MONO_TYPE_PTR:
2758         case MONO_TYPE_SZARRAY:
2759         case MONO_TYPE_ARRAY:
2760         case MONO_TYPE_VAR:
2761         case MONO_TYPE_MVAR:
2762         case MONO_TYPE_GENERICINST:
2763                 encode_type (assembly, type, &buf);
2764                 break;
2765         case MONO_TYPE_CLASS:
2766         case MONO_TYPE_VALUETYPE: {
2767                 MonoClass *k = mono_class_from_mono_type (type);
2768                 if (!k || !k->generic_container) {
2769                         sigbuffer_free (&buf);
2770                         return 0;
2771                 }
2772                 encode_type (assembly, type, &buf);
2773                 break;
2774         }
2775         default:
2776                 sigbuffer_free (&buf);
2777                 return 0;
2778         }
2779
2780         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2781         if (assembly->save) {
2782                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2783                 alloc_table (table, table->rows + 1);
2784                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2785                 values [MONO_TYPESPEC_SIGNATURE] = token;
2786         }
2787         sigbuffer_free (&buf);
2788
2789         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2790         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2791         table->next_idx ++;
2792         return token;
2793 }
2794
2795 static guint32
2796 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2797 {
2798         MONO_REQ_GC_UNSAFE_MODE;
2799
2800         MonoDynamicTable *table;
2801         guint32 *values;
2802         guint32 token, scope, enclosing;
2803         MonoClass *klass;
2804
2805         /* if the type requires a typespec, we must try that first*/
2806         if (try_typespec && (token = create_typespec (assembly, type)))
2807                 return token;
2808         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2809         if (token)
2810                 return token;
2811         klass = mono_class_from_mono_type (type);
2812         if (!klass)
2813                 klass = mono_class_from_mono_type (type);
2814
2815         /*
2816          * If it's in the same module and not a generic type parameter:
2817          */
2818         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2819                         (type->type != MONO_TYPE_MVAR)) {
2820                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2821                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2822                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2823                 return token;
2824         }
2825
2826         if (klass->nested_in) {
2827                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2828                 /* get the typeref idx of the enclosing type */
2829                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2830                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2831         } else {
2832                 scope = resolution_scope_from_image (assembly, klass->image);
2833         }
2834         table = &assembly->tables [MONO_TABLE_TYPEREF];
2835         if (assembly->save) {
2836                 alloc_table (table, table->rows + 1);
2837                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2838                 values [MONO_TYPEREF_SCOPE] = scope;
2839                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2840                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2841         }
2842         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2843         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2844         table->next_idx ++;
2845         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2846         return token;
2847 }
2848
2849 /*
2850  * Despite the name, we handle also TypeSpec (with the above helper).
2851  */
2852 static guint32
2853 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2854 {
2855         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2856 }
2857
2858 #ifndef DISABLE_REFLECTION_EMIT
2859 static guint32
2860 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2861 {
2862         MONO_REQ_GC_NEUTRAL_MODE;
2863
2864         MonoDynamicTable *table;
2865         guint32 *values;
2866         guint32 token, pclass;
2867
2868         switch (parent & MONO_TYPEDEFORREF_MASK) {
2869         case MONO_TYPEDEFORREF_TYPEREF:
2870                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2871                 break;
2872         case MONO_TYPEDEFORREF_TYPESPEC:
2873                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2874                 break;
2875         case MONO_TYPEDEFORREF_TYPEDEF:
2876                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2877                 break;
2878         default:
2879                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2880                 return 0;
2881         }
2882         /* extract the index */
2883         parent >>= MONO_TYPEDEFORREF_BITS;
2884
2885         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2886
2887         if (assembly->save) {
2888                 alloc_table (table, table->rows + 1);
2889                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2890                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2891                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2892                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2893         }
2894
2895         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2896         table->next_idx ++;
2897
2898         return token;
2899 }
2900
2901 /*
2902  * Insert a memberef row into the metadata: the token that point to the memberref
2903  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2904  * mono_image_get_fieldref_token()).
2905  * The sig param is an index to an already built signature.
2906  */
2907 static guint32
2908 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2909 {
2910         MONO_REQ_GC_NEUTRAL_MODE;
2911
2912         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2913         return mono_image_add_memberef_row (assembly, parent, name, sig);
2914 }
2915
2916
2917 static guint32
2918 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2919 {
2920         MONO_REQ_GC_NEUTRAL_MODE;
2921
2922         guint32 token;
2923         MonoMethodSignature *sig;
2924         
2925         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2926
2927         if (create_typespec) {
2928                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2929                 if (token)
2930                         return token;
2931         } 
2932
2933         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2934         if (token && !create_typespec)
2935                 return token;
2936
2937         g_assert (!method->is_inflated);
2938         if (!token) {
2939                 /*
2940                  * A methodref signature can't contain an unmanaged calling convention.
2941                  */
2942                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2943                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2944                         sig->call_convention = MONO_CALL_DEFAULT;
2945                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2946                         method->name,  method_encode_signature (assembly, sig));
2947                 g_free (sig);
2948                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2949         }
2950
2951         if (create_typespec) {
2952                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2953                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2954                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2955
2956                 if (assembly->save) {
2957                         guint32 *values;
2958
2959                         alloc_table (table, table->rows + 1);
2960                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2961                         values [MONO_METHODSPEC_METHOD] = token;
2962                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2963                 }
2964
2965                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2966                 table->next_idx ++;
2967                 /*methodspec and memberef tokens are diferent, */
2968                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2969                 return token;
2970         }
2971         return token;
2972 }
2973
2974 static guint32
2975 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2976 {
2977         guint32 token, parent, sig;
2978         ReflectionMethodBuilder rmb;
2979         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2980         
2981         mono_error_init (error);
2982         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2983         if (token)
2984                 return token;
2985
2986         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2987                 return 0;
2988
2989         /*
2990          * A methodref signature can't contain an unmanaged calling convention.
2991          * Since some flags are encoded as part of call_conv, we need to check against it.
2992         */
2993         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2994                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2995
2996         sig = method_builder_encode_signature (assembly, &rmb, error);
2997         return_val_if_nok (error, 0);
2998
2999         if (tb->generic_params) {
3000                 parent = create_generic_typespec (assembly, tb, error);
3001                 return_val_if_nok (error, 0);
3002         } else {
3003                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
3004                 return_val_if_nok (error, 0);
3005
3006                 parent = mono_image_typedef_or_ref (assembly, t);
3007         }
3008
3009         char *name = mono_string_to_utf8_checked (method->name, error);
3010         return_val_if_nok (error, 0);
3011
3012         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3013         g_free (name);
3014
3015         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3016
3017         return token;
3018 }
3019
3020 static guint32
3021 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
3022                                      const gchar *name, guint32 sig)
3023 {
3024         MonoDynamicTable *table;
3025         guint32 token;
3026         guint32 *values;
3027         
3028         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3029
3030         if (assembly->save) {
3031                 alloc_table (table, table->rows + 1);
3032                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3033                 values [MONO_MEMBERREF_CLASS] = original;
3034                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3035                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3036         }
3037
3038         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3039         table->next_idx ++;
3040
3041         return token;
3042 }
3043
3044 static guint32
3045 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3046 {
3047         SigBuffer buf;
3048         int i;
3049         guint32 nparams = mono_array_length (mb->generic_params);
3050         guint32 idx;
3051
3052         if (!assembly->save)
3053                 return 0;
3054
3055         sigbuffer_init (&buf, 32);
3056
3057         sigbuffer_add_value (&buf, 0xa);
3058         sigbuffer_add_value (&buf, nparams);
3059
3060         for (i = 0; i < nparams; i++) {
3061                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3062                 sigbuffer_add_value (&buf, i);
3063         }
3064
3065         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3066         sigbuffer_free (&buf);
3067         return idx;
3068 }
3069
3070 static guint32
3071 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3072 {
3073         MonoDynamicTable *table;
3074         guint32 *values;
3075         guint32 token, mtoken = 0;
3076
3077         mono_error_init (error);
3078         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3079         if (token)
3080                 return token;
3081
3082         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3083
3084         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3085         if (!mono_error_ok (error))
3086                 return 0;
3087
3088         switch (mono_metadata_token_table (mtoken)) {
3089         case MONO_TABLE_MEMBERREF:
3090                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3091                 break;
3092         case MONO_TABLE_METHOD:
3093                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3094                 break;
3095         default:
3096                 g_assert_not_reached ();
3097         }
3098
3099         if (assembly->save) {
3100                 alloc_table (table, table->rows + 1);
3101                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3102                 values [MONO_METHODSPEC_METHOD] = mtoken;
3103                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3104         }
3105
3106         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3107         table->next_idx ++;
3108
3109         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3110         return token;
3111 }
3112
3113 static guint32
3114 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3115 {
3116         guint32 token;
3117
3118         mono_error_init (error);
3119
3120         if (mb->generic_params && create_methodspec) 
3121                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3122
3123         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3124         if (token)
3125                 return token;
3126
3127         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3128         if (!mono_error_ok (error))
3129                 return 0;
3130         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3131         return token;
3132 }
3133
3134 static guint32
3135 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3136 {
3137         guint32 token, parent, sig;
3138         ReflectionMethodBuilder rmb;
3139         char *name;
3140         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3141         
3142         mono_error_init (error);
3143         
3144         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3145         if (token)
3146                 return token;
3147
3148         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3149                 return 0;
3150
3151         if (tb->generic_params) {
3152                 parent = create_generic_typespec (assembly, tb, error);
3153                 return_val_if_nok (error, 0);
3154         } else {
3155                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3156                 return_val_if_nok (error, 0);
3157                 parent = mono_image_typedef_or_ref (assembly, type);
3158         }
3159         
3160         name = mono_string_to_utf8_checked (rmb.name, error);
3161         return_val_if_nok (error, 0);
3162         sig = method_builder_encode_signature (assembly, &rmb, error);
3163         return_val_if_nok (error, 0);
3164
3165         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3166
3167         g_free (name);
3168         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3169         return token;
3170 }
3171 #endif
3172
3173 static gboolean
3174 is_field_on_inst (MonoClassField *field)
3175 {
3176         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3177 }
3178
3179 /*
3180  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3181  */
3182 static MonoType*
3183 get_field_on_inst_generic_type (MonoClassField *field)
3184 {
3185         MonoClass *klass, *gtd;
3186         MonoDynamicGenericClass *dgclass;
3187         int field_index;
3188
3189         g_assert (is_field_on_inst (field));
3190
3191         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3192
3193         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3194                 field_index = field - dgclass->fields;
3195                 return dgclass->field_generic_types [field_index];              
3196         }
3197
3198         klass = field->parent;
3199         gtd = klass->generic_class->container_class;
3200
3201         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3202                 field_index = field - klass->fields;
3203                 return gtd->fields [field_index].type;
3204         }
3205
3206         g_assert_not_reached ();
3207         return 0;
3208 }
3209
3210 #ifndef DISABLE_REFLECTION_EMIT
3211 static guint32
3212 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3213 {
3214         MonoType *type;
3215         guint32 token;
3216
3217         g_assert (field);
3218         g_assert (field->parent);
3219
3220         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3221         if (token)
3222                 return token;
3223
3224         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3225                 int index = field - field->parent->fields;
3226                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3227         } else {
3228                 if (is_field_on_inst (field))
3229                         type = get_field_on_inst_generic_type (field);
3230                 else
3231                         type = mono_field_get_type (field);
3232         }
3233         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3234                                                                                         mono_field_get_name (field),
3235                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3236         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3237         return token;
3238 }
3239
3240 static guint32
3241 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3242 {
3243         guint32 token;
3244         MonoClass *klass;
3245         MonoGenericClass *gclass;
3246         MonoType *type;
3247         char *name;
3248
3249         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3250         if (token)
3251                 return token;
3252         if (is_sre_field_builder (mono_object_class (f->fb))) {
3253                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3254                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3255                 return_val_if_nok (error, 0);
3256                 klass = mono_class_from_mono_type (type);
3257                 gclass = type->data.generic_class;
3258                 g_assert (gclass->is_dynamic);
3259
3260                 guint32 sig_token = field_encode_signature (assembly, fb, error);
3261                 return_val_if_nok (error, 0);
3262                 name = mono_string_to_utf8_checked (fb->name, error);
3263                 return_val_if_nok (error, 0);
3264                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3265                 g_free (name);          
3266         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3267                 guint32 sig;
3268                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3269
3270                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3271                 return_val_if_nok (error, 0);
3272                 klass = mono_class_from_mono_type (type);
3273
3274                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3275                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3276         } else {
3277                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3278                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3279         }
3280
3281         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3282         return token;
3283 }
3284
3285 static guint32
3286 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3287 {
3288         guint32 sig, token;
3289         MonoClass *klass;
3290         MonoGenericClass *gclass;
3291         MonoType *type;
3292
3293         mono_error_init (error);
3294
3295         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3296
3297         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3298         if (token)
3299                 return token;
3300
3301         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3302                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3303                 ReflectionMethodBuilder rmb;
3304                 char *name;
3305
3306                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3307                 return_val_if_nok (error, 0);
3308                 klass = mono_class_from_mono_type (type);
3309
3310                 gclass = type->data.generic_class;
3311                 g_assert (gclass->is_dynamic);
3312
3313                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3314                         return 0;
3315
3316                 sig = method_builder_encode_signature (assembly, &rmb, error);
3317                 return_val_if_nok (error, 0);
3318
3319                 name = mono_string_to_utf8_checked (rmb.name, error);
3320                 return_val_if_nok (error, 0);
3321
3322                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3323                 g_free (name);
3324         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3325                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3326
3327                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3328                 return_val_if_nok (error, 0);
3329                 klass = mono_class_from_mono_type (type);
3330
3331                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3332                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3333         } else {
3334                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3335                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3336         }
3337
3338
3339         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3340         return token;
3341 }
3342
3343 static MonoMethod*
3344 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3345 {
3346         MonoClass *klass;
3347         MonoGenericContext tmp_context;
3348         MonoType **type_argv;
3349         MonoGenericInst *ginst;
3350         MonoMethod *method, *inflated;
3351         int count, i;
3352
3353         mono_error_init (error);
3354
3355         init_type_builder_generics ((MonoObject*)m->inst, error);
3356         return_val_if_nok (error, NULL);
3357
3358         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3359         return_val_if_nok (error, NULL);
3360
3361         klass = method->klass;
3362
3363         if (m->method_args == NULL)
3364                 return method;
3365
3366         if (method->is_inflated)
3367                 method = ((MonoMethodInflated *) method)->declaring;
3368
3369         count = mono_array_length (m->method_args);
3370
3371         type_argv = g_new0 (MonoType *, count);
3372         for (i = 0; i < count; i++) {
3373                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3374                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3375                 return_val_if_nok (error, NULL);
3376         }
3377         ginst = mono_metadata_get_generic_inst (count, type_argv);
3378         g_free (type_argv);
3379
3380         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3381         tmp_context.method_inst = ginst;
3382
3383         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3384         mono_error_assert_ok (error);
3385         return inflated;
3386 }
3387
3388 static guint32
3389 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3390 {
3391         guint32 sig, token = 0;
3392         MonoType *type;
3393         MonoClass *klass;
3394
3395         mono_error_init (error);
3396
3397         if (m->method_args) {
3398                 MonoMethod *inflated;
3399
3400                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3401                 return_val_if_nok (error, 0);
3402
3403                 if (create_methodspec)
3404                         token = mono_image_get_methodspec_token (assembly, inflated);
3405                 else
3406                         token = mono_image_get_inflated_method_token (assembly, inflated);
3407                 return token;
3408         }
3409
3410         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3411         if (token)
3412                 return token;
3413
3414         if (is_sre_method_builder (mono_object_class (m->mb))) {
3415                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3416                 MonoGenericClass *gclass;
3417                 ReflectionMethodBuilder rmb;
3418                 char *name;
3419
3420                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3421                 return_val_if_nok (error, 0);
3422                 klass = mono_class_from_mono_type (type);
3423                 gclass = type->data.generic_class;
3424                 g_assert (gclass->is_dynamic);
3425
3426                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3427                         return 0;
3428
3429                 sig = method_builder_encode_signature (assembly, &rmb, error);
3430                 return_val_if_nok (error, 0);
3431
3432                 name = mono_string_to_utf8_checked (rmb.name, error);
3433                 return_val_if_nok (error, 0);
3434
3435                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3436                 g_free (name);          
3437         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3438                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3439
3440                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3441                 return_val_if_nok (error, 0);
3442                 klass = mono_class_from_mono_type (type);
3443
3444                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3445                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3446         } else {
3447                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3448                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3449         }
3450
3451         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3452         return token;
3453 }
3454
3455 static guint32
3456 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3457 {
3458         SigBuffer buf;
3459         int i;
3460         guint32 nparams = context->method_inst->type_argc;
3461         guint32 idx;
3462
3463         if (!assembly->save)
3464                 return 0;
3465
3466         sigbuffer_init (&buf, 32);
3467         /*
3468          * FIXME: vararg, explicit_this, differenc call_conv values...
3469          */
3470         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3471         sigbuffer_add_value (&buf, nparams);
3472
3473         for (i = 0; i < nparams; i++)
3474                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3475
3476         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3477         sigbuffer_free (&buf);
3478         return idx;
3479 }
3480
3481 static guint32
3482 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3483 {
3484         MonoDynamicTable *table;
3485         guint32 *values;
3486         guint32 token, mtoken = 0, sig;
3487         MonoMethodInflated *imethod;
3488         MonoMethod *declaring;
3489
3490         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3491
3492         g_assert (method->is_inflated);
3493         imethod = (MonoMethodInflated *) method;
3494         declaring = imethod->declaring;
3495
3496         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3497         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3498
3499         if (!mono_method_signature (declaring)->generic_param_count)
3500                 return mtoken;
3501
3502         switch (mono_metadata_token_table (mtoken)) {
3503         case MONO_TABLE_MEMBERREF:
3504                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3505                 break;
3506         case MONO_TABLE_METHOD:
3507                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3508                 break;
3509         default:
3510                 g_assert_not_reached ();
3511         }
3512
3513         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3514
3515         if (assembly->save) {
3516                 alloc_table (table, table->rows + 1);
3517                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3518                 values [MONO_METHODSPEC_METHOD] = mtoken;
3519                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3520         }
3521
3522         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3523         table->next_idx ++;
3524
3525         return token;
3526 }
3527
3528 static guint32
3529 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3530 {
3531         MonoMethodInflated *imethod;
3532         guint32 token;
3533         
3534         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3535         if (token)
3536                 return token;
3537
3538         g_assert (method->is_inflated);
3539         imethod = (MonoMethodInflated *) method;
3540
3541         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3542                 token = method_encode_methodspec (assembly, method);
3543         } else {
3544                 guint32 sig = method_encode_signature (
3545                         assembly, mono_method_signature (imethod->declaring));
3546                 token = mono_image_get_memberref_token (
3547                         assembly, &method->klass->byval_arg, method->name, sig);
3548         }
3549
3550         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3551         return token;
3552 }
3553
3554 static guint32
3555 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3556 {
3557         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3558         guint32 sig, token;
3559
3560         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3561         token = mono_image_get_memberref_token (
3562                 assembly, &m->klass->byval_arg, m->name, sig);
3563
3564         return token;
3565 }
3566
3567 static guint32
3568 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3569 {
3570         MonoDynamicTable *table;
3571         MonoClass *klass;
3572         MonoType *type;
3573         guint32 *values;
3574         guint32 token;
3575         SigBuffer buf;
3576         int count, i;
3577
3578         /*
3579          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3580          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3581          * Because of this, we must not insert it into the `typeref' hash table.
3582          */
3583         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3584         return_val_if_nok (error, 0);
3585         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3586         if (token)
3587                 return token;
3588
3589         sigbuffer_init (&buf, 32);
3590
3591         g_assert (tb->generic_params);
3592         klass = mono_class_from_mono_type (type);
3593
3594         if (tb->generic_container) {
3595                 if (!mono_reflection_create_generic_class (tb, error))
3596                         goto fail;
3597         }
3598
3599         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3600         g_assert (klass->generic_container);
3601         sigbuffer_add_value (&buf, klass->byval_arg.type);
3602         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3603
3604         count = mono_array_length (tb->generic_params);
3605         sigbuffer_add_value (&buf, count);
3606         for (i = 0; i < count; i++) {
3607                 MonoReflectionGenericParam *gparam;
3608
3609                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3610                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3611                 if (!is_ok (error))
3612                         goto fail;
3613
3614                 encode_type (assembly, gparam_type, &buf);
3615         }
3616
3617         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3618
3619         if (assembly->save) {
3620                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3621                 alloc_table (table, table->rows + 1);
3622                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3623                 values [MONO_TYPESPEC_SIGNATURE] = token;
3624         }
3625         sigbuffer_free (&buf);
3626
3627         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3628         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3629         table->next_idx ++;
3630         return token;
3631 fail:
3632         sigbuffer_free (&buf);
3633         return 0;
3634 }
3635
3636 /*
3637  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3638  */
3639 static MonoType*
3640 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3641 {
3642         int i, count, len, pos;
3643         MonoType *t;
3644
3645         mono_error_init (error);
3646
3647         count = 0;
3648         if (modreq)
3649                 count += mono_array_length (modreq);
3650         if (modopt)
3651                 count += mono_array_length (modopt);
3652
3653         if (count == 0)
3654                 return mono_metadata_type_dup (NULL, type);
3655
3656         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3657         t = (MonoType *)g_malloc (len);
3658         memcpy (t, type, MONO_SIZEOF_TYPE);
3659
3660         t->num_mods = count;
3661         pos = 0;
3662         if (modreq) {
3663                 for (i = 0; i < mono_array_length (modreq); ++i) {
3664                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3665                         if (!is_ok (error))
3666                                 goto fail;
3667                         t->modifiers [pos].required = 1;
3668                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3669                         pos ++;
3670                 }
3671         }
3672         if (modopt) {
3673                 for (i = 0; i < mono_array_length (modopt); ++i) {
3674                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3675                         if (!is_ok (error))
3676                                 goto fail;
3677                         t->modifiers [pos].required = 0;
3678                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3679                         pos ++;
3680                 }
3681         }
3682
3683         return t;
3684 fail:
3685         g_free (t);
3686         return NULL;
3687 }
3688
3689 static void
3690 init_type_builder_generics (MonoObject *type, MonoError *error)
3691 {
3692         MonoReflectionTypeBuilder *tb;
3693
3694         mono_error_init (error);
3695
3696         if (!is_sre_type_builder(mono_object_class (type)))
3697                 return;
3698         tb = (MonoReflectionTypeBuilder *)type;
3699
3700         if (tb && tb->generic_container)
3701                 mono_reflection_create_generic_class (tb, error);
3702 }
3703
3704 static guint32
3705 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3706 {
3707         MonoDynamicTable *table;
3708         MonoType *custom = NULL, *type;
3709         guint32 *values;
3710         guint32 token, pclass, parent, sig;
3711         gchar *name;
3712
3713         mono_error_init (error);
3714
3715         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3716         if (token)
3717                 return token;
3718
3719         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3720         return_val_if_nok (error, 0);
3721         /* FIXME: is this call necessary? */
3722         mono_class_from_mono_type (typeb);
3723
3724         /*FIXME this is one more layer of ugliness due how types are created.*/
3725         init_type_builder_generics (fb->type, error);
3726         return_val_if_nok (error, 0);
3727
3728         /* fb->type does not include the custom modifiers */
3729         /* FIXME: We should do this in one place when a fieldbuilder is created */
3730         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3731         return_val_if_nok (error, 0);
3732
3733         if (fb->modreq || fb->modopt) {
3734                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3735                 return_val_if_nok (error, 0);
3736         }
3737
3738         sig = fieldref_encode_signature (assembly, NULL, type);
3739         g_free (custom);
3740
3741         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3742         return_val_if_nok (error, 0);
3743         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3744         
3745         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3746         parent >>= MONO_TYPEDEFORREF_BITS;
3747
3748         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3749
3750         name = mono_string_to_utf8_checked (fb->name, error);
3751         return_val_if_nok (error, 0);
3752
3753         if (assembly->save) {
3754                 alloc_table (table, table->rows + 1);
3755                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3756                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3757                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3758                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3759         }
3760
3761         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3762         table->next_idx ++;
3763         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3764         g_free (name);
3765         return token;
3766 }
3767
3768 static guint32
3769 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3770 {
3771         SigBuffer buf;
3772         guint32 nargs;
3773         guint32 i, idx;
3774
3775         mono_error_init (error);
3776
3777         if (!assembly->save)
3778                 return 0;
3779
3780         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3781         g_assert (helper->type == 2);
3782
3783         if (helper->arguments)
3784                 nargs = mono_array_length (helper->arguments);
3785         else
3786                 nargs = 0;
3787
3788         sigbuffer_init (&buf, 32);
3789
3790         /* Encode calling convention */
3791         /* Change Any to Standard */
3792         if ((helper->call_conv & 0x03) == 0x03)
3793                 helper->call_conv = 0x01;
3794         /* explicit_this implies has_this */
3795         if (helper->call_conv & 0x40)
3796                 helper->call_conv &= 0x20;
3797
3798         if (helper->call_conv == 0) { /* Unmanaged */
3799                 idx = helper->unmanaged_call_conv - 1;
3800         } else {
3801                 /* Managed */
3802                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3803                 if (helper->call_conv & 0x02) /* varargs */
3804                         idx += 0x05;
3805         }
3806
3807         sigbuffer_add_byte (&buf, idx);
3808         sigbuffer_add_value (&buf, nargs);
3809         encode_reflection_type (assembly, helper->return_type, &buf, error);
3810         if (!is_ok (error))
3811                 goto fail;
3812         for (i = 0; i < nargs; ++i) {
3813                 MonoArray *modreqs = NULL;
3814                 MonoArray *modopts = NULL;
3815                 MonoReflectionType *pt;
3816
3817                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3818                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3819                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3820                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3821
3822                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3823                 if (!is_ok (error))
3824                         goto fail;
3825                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3826                 encode_reflection_type (assembly, pt, &buf, error);
3827                 if (!is_ok (error))
3828                         goto fail;
3829         }
3830         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3831         sigbuffer_free (&buf);
3832
3833         return idx;
3834 fail:
3835         sigbuffer_free (&buf);
3836         return 0;
3837 }
3838
3839 static guint32 
3840 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3841 {
3842         guint32 idx;
3843         MonoDynamicTable *table;
3844         guint32 *values;
3845
3846         mono_error_init (error);
3847
3848         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3849         idx = table->next_idx ++;
3850         table->rows ++;
3851         alloc_table (table, table->rows);
3852         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3853
3854         values [MONO_STAND_ALONE_SIGNATURE] =
3855                 mono_reflection_encode_sighelper (assembly, helper, error);
3856         return_val_if_nok (error, 0);
3857         
3858         return idx;
3859 }
3860
3861 static int
3862 reflection_cc_to_file (int call_conv) {
3863         switch (call_conv & 0x3) {
3864         case 0:
3865         case 1: return MONO_CALL_DEFAULT;
3866         case 2: return MONO_CALL_VARARG;
3867         default:
3868                 g_assert_not_reached ();
3869         }
3870         return 0;
3871 }
3872 #endif /* !DISABLE_REFLECTION_EMIT */
3873
3874 typedef struct {
3875         MonoType *parent;
3876         MonoMethodSignature *sig;
3877         char *name;
3878         guint32 token;
3879 } ArrayMethod;
3880
3881 #ifndef DISABLE_REFLECTION_EMIT
3882 static guint32
3883 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3884 {
3885         guint32 nparams, i;
3886         GList *tmp;
3887         char *name = NULL;
3888         MonoMethodSignature *sig;
3889         ArrayMethod *am = NULL;
3890         MonoType *mtype;
3891
3892         mono_error_init (error);
3893
3894         nparams = mono_array_length (m->parameters);
3895         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3896         sig->hasthis = 1;
3897         sig->sentinelpos = -1;
3898         sig->call_convention = reflection_cc_to_file (m->call_conv);
3899         sig->param_count = nparams;
3900         if (m->ret) {
3901                 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3902                 if (!is_ok (error))
3903                         goto fail;
3904         } else
3905                 sig->ret = &mono_defaults.void_class->byval_arg;
3906
3907         mtype = mono_reflection_type_get_handle (m->parent, error);
3908         if (!is_ok (error))
3909                 goto fail;
3910
3911         for (i = 0; i < nparams; ++i) {
3912                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3913                 if (!is_ok (error))
3914                         goto fail;
3915         }
3916
3917         name = mono_string_to_utf8_checked (m->name, error);
3918         if (!is_ok (error))
3919                 goto fail;
3920         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3921                 am = (ArrayMethod *)tmp->data;
3922                 if (strcmp (name, am->name) == 0 && 
3923                                 mono_metadata_type_equal (am->parent, mtype) &&
3924                                 mono_metadata_signature_equal (am->sig, sig)) {
3925                         g_free (name);
3926                         g_free (sig);
3927                         m->table_idx = am->token & 0xffffff;
3928                         return am->token;
3929                 }
3930         }
3931         am = g_new0 (ArrayMethod, 1);
3932         am->name = name;
3933         am->sig = sig;
3934         am->parent = mtype;
3935         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3936                 method_encode_signature (assembly, sig));
3937         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3938         m->table_idx = am->token & 0xffffff;
3939         return am->token;
3940 fail:
3941         g_free (am);
3942         g_free (name);
3943         g_free (sig);
3944         return 0;
3945
3946 }
3947
3948 /*
3949  * Insert into the metadata tables all the info about the TypeBuilder tb.
3950  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3951  */
3952 static gboolean
3953 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3954 {
3955         MonoDynamicTable *table;
3956         guint *values;
3957         int i, is_object = 0, is_system = 0;
3958         char *n;
3959
3960         mono_error_init (error);
3961
3962         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3963         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3964         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3965         n = mono_string_to_utf8_checked (tb->name, error);
3966         return_val_if_nok (error, FALSE);
3967         if (strcmp (n, "Object") == 0)
3968                 is_object++;
3969         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3970         g_free (n);
3971         n = mono_string_to_utf8_checked (tb->nspace, error);
3972         return_val_if_nok (error, FALSE);
3973         if (strcmp (n, "System") == 0)
3974                 is_system++;
3975         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3976         g_free (n);
3977         if (tb->parent && !(is_system && is_object) && 
3978                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3979                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3980                 return_val_if_nok (error, FALSE);
3981                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3982         } else {
3983                 values [MONO_TYPEDEF_EXTENDS] = 0;
3984         }
3985         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3986         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3987
3988         /*
3989          * if we have explicitlayout or sequentiallayouts, output data in the
3990          * ClassLayout table.
3991          */
3992         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3993                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3994                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3995                 table->rows++;
3996                 alloc_table (table, table->rows);
3997                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3998                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3999                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
4000                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
4001         }
4002
4003         /* handle interfaces */
4004         if (tb->interfaces) {
4005                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4006                 i = table->rows;
4007                 table->rows += mono_array_length (tb->interfaces);
4008                 alloc_table (table, table->rows);
4009                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
4010                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
4011                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
4012                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
4013                         return_val_if_nok (error, FALSE);
4014                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
4015                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
4016                         values += MONO_INTERFACEIMPL_SIZE;
4017                 }
4018         }
4019
4020         /* handle fields */
4021         if (tb->fields) {
4022                 table = &assembly->tables [MONO_TABLE_FIELD];
4023                 table->rows += tb->num_fields;
4024                 alloc_table (table, table->rows);
4025                 for (i = 0; i < tb->num_fields; ++i) {
4026                         mono_image_get_field_info (
4027                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
4028                         return_val_if_nok (error, FALSE);
4029                 }
4030         }
4031
4032         /* handle constructors */
4033         if (tb->ctors) {
4034                 table = &assembly->tables [MONO_TABLE_METHOD];
4035                 table->rows += mono_array_length (tb->ctors);
4036                 alloc_table (table, table->rows);
4037                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4038                         if (!mono_image_get_ctor_info (domain,
4039                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
4040                                                        assembly, error))
4041                                 return FALSE;
4042                 }
4043         }
4044
4045         /* handle methods */
4046         if (tb->methods) {
4047                 table = &assembly->tables [MONO_TABLE_METHOD];
4048                 table->rows += tb->num_methods;
4049                 alloc_table (table, table->rows);
4050                 for (i = 0; i < tb->num_methods; ++i) {
4051                         if (!mono_image_get_method_info (
4052                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4053                                 return FALSE;
4054                 }
4055         }
4056
4057         /* Do the same with properties etc.. */
4058         if (tb->events && mono_array_length (tb->events)) {
4059                 table = &assembly->tables [MONO_TABLE_EVENT];
4060                 table->rows += mono_array_length (tb->events);
4061                 alloc_table (table, table->rows);
4062                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4063                 table->rows ++;
4064                 alloc_table (table, table->rows);
4065                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4066                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4067                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4068                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4069                         mono_image_get_event_info (
4070                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4071                         return_val_if_nok (error, FALSE);
4072                 }
4073         }
4074         if (tb->properties && mono_array_length (tb->properties)) {
4075                 table = &assembly->tables [MONO_TABLE_PROPERTY];
4076                 table->rows += mono_array_length (tb->properties);
4077                 alloc_table (table, table->rows);
4078                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4079                 table->rows ++;
4080                 alloc_table (table, table->rows);
4081                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4082                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4083                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4084                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4085                         mono_image_get_property_info (
4086                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4087                         return_val_if_nok (error, FALSE);
4088                 }
4089         }
4090
4091         /* handle generic parameters */
4092         if (tb->generic_params) {
4093                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4094                 table->rows += mono_array_length (tb->generic_params);
4095                 alloc_table (table, table->rows);
4096                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4097                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4098
4099                         mono_image_get_generic_param_info (
4100                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4101                 }
4102         }
4103
4104         mono_image_add_decl_security (assembly, 
4105                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4106
4107         if (tb->subtypes) {
4108                 MonoDynamicTable *ntable;
4109                 
4110                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4111                 ntable->rows += mono_array_length (tb->subtypes);
4112                 alloc_table (ntable, ntable->rows);
4113                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4114
4115                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4116                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4117
4118                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4119                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4120                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4121                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4122                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4123                                 ntable->next_idx, ntable->rows);*/
4124                         values += MONO_NESTED_CLASS_SIZE;
4125                         ntable->next_idx++;
4126                 }
4127         }
4128
4129         return TRUE;
4130 }
4131 #endif
4132
4133 static void
4134 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4135 {
4136         int i;
4137
4138         mono_ptr_array_append (*types, type);
4139
4140         if (!type->subtypes)
4141                 return;
4142
4143         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4144                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4145                 collect_types (types, subtype);
4146         }
4147 }
4148
4149 static gint
4150 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4151 {
4152         if ((*type1)->table_idx < (*type2)->table_idx)
4153                 return -1;
4154         else
4155                 if ((*type1)->table_idx > (*type2)->table_idx)
4156                         return 1;
4157         else
4158                 return 0;
4159 }
4160
4161 static gboolean
4162 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4163         int i;
4164
4165         mono_error_init (error);
4166         if (!pinfo)
4167                 return TRUE;
4168         for (i = 0; i < mono_array_length (pinfo); ++i) {
4169                 MonoReflectionParamBuilder *pb;
4170                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4171                 if (!pb)
4172                         continue;
4173                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4174                         return FALSE;
4175         }
4176
4177         return TRUE;
4178 }
4179
4180 static gboolean
4181 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4182         int i;
4183
4184         mono_error_init (error);
4185         
4186         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4187                 return FALSE;
4188         if (tb->fields) {
4189                 for (i = 0; i < tb->num_fields; ++i) {
4190                         MonoReflectionFieldBuilder* fb;
4191                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4192                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4193                                 return FALSE;
4194                 }
4195         }
4196         if (tb->events) {
4197                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4198                         MonoReflectionEventBuilder* eb;
4199                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4200                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4201                                 return FALSE;
4202                 }
4203         }
4204         if (tb->properties) {
4205                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4206                         MonoReflectionPropertyBuilder* pb;
4207                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4208                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4209                                 return FALSE;
4210                 }
4211         }
4212         if (tb->ctors) {
4213                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4214                         MonoReflectionCtorBuilder* cb;
4215                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4216                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4217                             !params_add_cattrs (assembly, cb->pinfo, error))
4218                                 return FALSE;
4219                 }
4220         }
4221
4222         if (tb->methods) {
4223                 for (i = 0; i < tb->num_methods; ++i) {
4224                         MonoReflectionMethodBuilder* mb;
4225                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4226                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4227                             !params_add_cattrs (assembly, mb->pinfo, error))
4228                                 return FALSE;
4229                 }
4230         }
4231
4232         if (tb->subtypes) {
4233                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4234                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4235                                 return FALSE;
4236                 }
4237         }
4238
4239         return TRUE;
4240 }
4241
4242 static gboolean
4243 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4244 {
4245         int i;
4246         
4247         mono_error_init (error);
4248
4249         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4250                 return FALSE;
4251
4252         if (moduleb->global_methods) {
4253                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4254                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4255                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4256                             !params_add_cattrs (assembly, mb->pinfo, error))
4257                                 return FALSE;
4258                 }
4259         }
4260
4261         if (moduleb->global_fields) {
4262                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4263                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4264                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4265                                 return FALSE;
4266                 }
4267         }
4268         
4269         if (moduleb->types) {
4270                 for (i = 0; i < moduleb->num_types; ++i) {
4271                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4272                                 return FALSE;
4273                 }
4274         }
4275
4276         return TRUE;
4277 }
4278
4279 static gboolean
4280 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly, MonoError *error)
4281 {
4282         MonoDynamicTable *table;
4283         guint32 *values;
4284         char blob_size [6];
4285         guchar hash [20];
4286         char *b = blob_size;
4287         char *dir, *path;
4288
4289         mono_error_init (error);
4290
4291         table = &assembly->tables [MONO_TABLE_FILE];
4292         table->rows++;
4293         alloc_table (table, table->rows);
4294         values = table->values + table->next_idx * MONO_FILE_SIZE;
4295         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4296         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4297         if (image_is_dynamic (module->image)) {
4298                 /* This depends on the fact that the main module is emitted last */
4299                 dir = mono_string_to_utf8_checked (((MonoReflectionModuleBuilder*)module)->assemblyb->dir, error);
4300                 return_val_if_nok (error, FALSE);
4301                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4302         } else {
4303                 dir = NULL;
4304                 path = g_strdup (module->image->name);
4305         }
4306         mono_sha1_get_digest_from_file (path, hash);
4307         g_free (dir);
4308         g_free (path);
4309         mono_metadata_encode_value (20, b, &b);
4310         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4311         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4312         table->next_idx ++;
4313         return TRUE;
4314 }
4315
4316 static void
4317 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
4318 {
4319         MonoDynamicTable *table;
4320         int i;
4321
4322         mono_error_init (error);
4323
4324         table = &assembly->tables [MONO_TABLE_MODULE];
4325         mb->table_idx = table->next_idx ++;
4326         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name, error);
4327         return_if_nok (error);
4328         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4329         i /= 16;
4330         ++i;
4331         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4332         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4333         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4334         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4335 }
4336
4337 static guint32
4338 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4339         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4340 {
4341         MonoDynamicTable *table;
4342         guint32 *values;
4343         guint32 visib, res;
4344
4345         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4346         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4347                 return 0;
4348
4349         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4350         table->rows++;
4351         alloc_table (table, table->rows);
4352         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4353
4354         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4355         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4356         if (klass->nested_in)
4357                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4358         else
4359                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4360         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4361         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4362
4363         res = table->next_idx;
4364
4365         table->next_idx ++;
4366
4367         /* Emit nested types */
4368         if (klass->ext && klass->ext->nested_classes) {
4369                 GList *tmp;
4370
4371                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4372                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4373         }
4374
4375         return res;
4376 }
4377
4378 static void
4379 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4380                               guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4381                               MonoError *error)
4382 {
4383         MonoClass *klass;
4384         guint32 idx, i;
4385
4386         mono_error_init (error);
4387
4388         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4389         return_if_nok (error);
4390
4391         klass = mono_class_from_mono_type (t);
4392
4393         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4394
4395         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4396                                                                                                    parent_index, assembly);
4397
4398         /* 
4399          * Emit nested types
4400          * We need to do this ourselves since klass->nested_classes is not set up.
4401          */
4402         if (tb->subtypes) {
4403                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4404                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4405                         return_if_nok (error);
4406                 }
4407         }
4408 }
4409
4410 static void
4411 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4412         guint32 module_index, MonoDynamicImage *assembly)
4413 {
4414         MonoImage *image = module->image;
4415         MonoTableInfo  *t;
4416         guint32 i;
4417
4418         t = &image->tables [MONO_TABLE_TYPEDEF];
4419
4420         for (i = 0; i < t->rows; ++i) {
4421                 MonoError error;
4422                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4423                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4424
4425                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4426                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4427         }
4428 }
4429
4430 static void
4431 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4432 {
4433         MonoDynamicTable *table;
4434         guint32 *values;
4435         guint32 scope, scope_idx, impl, current_idx;
4436         gboolean forwarder = TRUE;
4437         gpointer iter = NULL;
4438         MonoClass *nested;
4439
4440         if (klass->nested_in) {
4441                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4442                 forwarder = FALSE;
4443         } else {
4444                 scope = resolution_scope_from_image (assembly, klass->image);
4445                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4446                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4447                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4448         }
4449
4450         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4451
4452         table->rows++;
4453         alloc_table (table, table->rows);
4454         current_idx = table->next_idx;
4455         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4456
4457         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4458         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4459         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4460         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4461         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4462
4463         table->next_idx++;
4464
4465         while ((nested = mono_class_get_nested_types (klass, &iter)))
4466                 add_exported_type (assemblyb, assembly, nested, current_idx);
4467 }
4468
4469 static void
4470 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4471 {
4472         MonoError error;
4473         MonoClass *klass;
4474         int i;
4475
4476         if (!assemblyb->type_forwarders)
4477                 return;
4478
4479         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4480                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4481                 MonoType *type;
4482                 if (!t)
4483                         continue;
4484
4485                 type = mono_reflection_type_get_handle (t, &error);
4486                 mono_error_assert_ok (&error);
4487                 g_assert (type);
4488
4489                 klass = mono_class_from_mono_type (type);
4490
4491                 add_exported_type (assemblyb, assembly, klass, 0);
4492         }
4493 }
4494
4495 #define align_pointer(base,p)\
4496         do {\
4497                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4498                 if (__diff & 3)\
4499                         (p) += 4 - (__diff & 3);\
4500         } while (0)
4501
4502 static int
4503 compare_constants (const void *a, const void *b)
4504 {
4505         const guint32 *a_values = (const guint32 *)a;
4506         const guint32 *b_values = (const guint32 *)b;
4507         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4508 }
4509
4510 static int
4511 compare_semantics (const void *a, const void *b)
4512 {
4513         const guint32 *a_values = (const guint32 *)a;
4514         const guint32 *b_values = (const guint32 *)b;
4515         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4516         if (assoc)
4517                 return assoc;
4518         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4519 }
4520
4521 static int
4522 compare_custom_attrs (const void *a, const void *b)
4523 {
4524         const guint32 *a_values = (const guint32 *)a;
4525         const guint32 *b_values = (const guint32 *)b;
4526
4527         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4528 }
4529
4530 static int
4531 compare_field_marshal (const void *a, const void *b)
4532 {
4533         const guint32 *a_values = (const guint32 *)a;
4534         const guint32 *b_values = (const guint32 *)b;
4535
4536         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4537 }
4538
4539 static int
4540 compare_nested (const void *a, const void *b)
4541 {
4542         const guint32 *a_values = (const guint32 *)a;
4543         const guint32 *b_values = (const guint32 *)b;
4544
4545         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4546 }
4547
4548 static int
4549 compare_genericparam (const void *a, const void *b)
4550 {
4551         MonoError error;
4552         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4553         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4554
4555         if ((*b_entry)->owner == (*a_entry)->owner) {
4556                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4557                 mono_error_assert_ok (&error);
4558                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4559                 mono_error_assert_ok (&error);
4560                 return 
4561                         mono_type_get_generic_param_num (a_type) -
4562                         mono_type_get_generic_param_num (b_type);
4563         } else
4564                 return (*a_entry)->owner - (*b_entry)->owner;
4565 }
4566
4567 static int
4568 compare_declsecurity_attrs (const void *a, const void *b)
4569 {
4570         const guint32 *a_values = (const guint32 *)a;
4571         const guint32 *b_values = (const guint32 *)b;
4572
4573         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4574 }
4575
4576 static int
4577 compare_interface_impl (const void *a, const void *b)
4578 {
4579         const guint32 *a_values = (const guint32 *)a;
4580         const guint32 *b_values = (const guint32 *)b;
4581
4582         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4583         if (klass)
4584                 return klass;
4585
4586         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4587 }
4588
4589 static void
4590 pad_heap (MonoDynamicStream *sh)
4591 {
4592         if (sh->index & 3) {
4593                 int sz = 4 - (sh->index & 3);
4594                 memset (sh->data + sh->index, 0, sz);
4595                 sh->index += sz;
4596         }
4597 }
4598
4599 struct StreamDesc {
4600         const char *name;
4601         MonoDynamicStream *stream;
4602 };
4603
4604 /*
4605  * build_compressed_metadata() fills in the blob of data that represents the 
4606  * raw metadata as it will be saved in the PE file. The five streams are output 
4607  * and the metadata tables are comnpressed from the guint32 array representation, 
4608  * to the compressed on-disk format.
4609  */
4610 static gboolean
4611 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4612 {
4613         MonoDynamicTable *table;
4614         int i;
4615         guint64 valid_mask = 0;
4616         guint64 sorted_mask;
4617         guint32 heapt_size = 0;
4618         guint32 meta_size = 256; /* allow for header and other stuff */
4619         guint32 table_offset;
4620         guint32 ntables = 0;
4621         guint64 *int64val;
4622         guint32 *int32val;
4623         guint16 *int16val;
4624         MonoImage *meta;
4625         unsigned char *p;
4626         struct StreamDesc stream_desc [5];
4627
4628         mono_error_init (error);
4629
4630         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4631         for (i = 0; i < assembly->gen_params->len; i++) {
4632                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4633                 if (!write_generic_param_entry (assembly, entry, error))
4634                         return FALSE;
4635         }
4636
4637         stream_desc [0].name  = "#~";
4638         stream_desc [0].stream = &assembly->tstream;
4639         stream_desc [1].name  = "#Strings";
4640         stream_desc [1].stream = &assembly->sheap;
4641         stream_desc [2].name  = "#US";
4642         stream_desc [2].stream = &assembly->us;
4643         stream_desc [3].name  = "#Blob";
4644         stream_desc [3].stream = &assembly->blob;
4645         stream_desc [4].name  = "#GUID";
4646         stream_desc [4].stream = &assembly->guid;
4647         
4648         /* tables that are sorted */
4649         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4650                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4651                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4652                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4653                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4654                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4655                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4656         
4657         /* Compute table sizes */
4658         /* the MonoImage has already been created in mono_image_basic_init() */
4659         meta = &assembly->image;
4660
4661         /* sizes should be multiple of 4 */
4662         pad_heap (&assembly->blob);
4663         pad_heap (&assembly->guid);
4664         pad_heap (&assembly->sheap);
4665         pad_heap (&assembly->us);
4666
4667         /* Setup the info used by compute_sizes () */
4668         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4669         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4670         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4671
4672         meta_size += assembly->blob.index;
4673         meta_size += assembly->guid.index;
4674         meta_size += assembly->sheap.index;
4675         meta_size += assembly->us.index;
4676
4677         for (i=0; i < MONO_TABLE_NUM; ++i)
4678                 meta->tables [i].rows = assembly->tables [i].rows;
4679         
4680         for (i = 0; i < MONO_TABLE_NUM; i++){
4681                 if (meta->tables [i].rows == 0)
4682                         continue;
4683                 valid_mask |= (guint64)1 << i;
4684                 ntables ++;
4685                 meta->tables [i].row_size = mono_metadata_compute_size (
4686                         meta, i, &meta->tables [i].size_bitfield);
4687                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4688         }
4689         heapt_size += 24; /* #~ header size */
4690         heapt_size += ntables * 4;
4691         /* make multiple of 4 */
4692         heapt_size += 3;
4693         heapt_size &= ~3;
4694         meta_size += heapt_size;
4695         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4696         p = (unsigned char*)meta->raw_metadata;
4697         /* the metadata signature */
4698         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4699         /* version numbers and 4 bytes reserved */
4700         int16val = (guint16*)p;
4701         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4702         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4703         p += 8;
4704         /* version string */
4705         int32val = (guint32*)p;
4706         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4707         p += 4;
4708         memcpy (p, meta->version, strlen (meta->version));
4709         p += GUINT32_FROM_LE (*int32val);
4710         align_pointer (meta->raw_metadata, p);
4711         int16val = (guint16*)p;
4712         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4713         *int16val = GUINT16_TO_LE (5); /* number of streams */
4714         p += 4;
4715
4716         /*
4717          * write the stream info.
4718          */
4719         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4720         table_offset += 3; table_offset &= ~3;
4721
4722         assembly->tstream.index = heapt_size;
4723         for (i = 0; i < 5; ++i) {
4724                 int32val = (guint32*)p;
4725                 stream_desc [i].stream->offset = table_offset;
4726                 *int32val++ = GUINT32_TO_LE (table_offset);
4727                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4728                 table_offset += GUINT32_FROM_LE (*int32val);
4729                 table_offset += 3; table_offset &= ~3;
4730                 p += 8;
4731                 strcpy ((char*)p, stream_desc [i].name);
4732                 p += strlen (stream_desc [i].name) + 1;
4733                 align_pointer (meta->raw_metadata, p);
4734         }
4735         /* 
4736          * now copy the data, the table stream header and contents goes first.
4737          */
4738         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4739         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4740         int32val = (guint32*)p;
4741         *int32val = GUINT32_TO_LE (0); /* reserved */
4742         p += 4;
4743
4744         *p++ = 2; /* version */
4745         *p++ = 0;
4746
4747         if (meta->idx_string_wide)
4748                 *p |= 0x01;
4749         if (meta->idx_guid_wide)
4750                 *p |= 0x02;
4751         if (meta->idx_blob_wide)
4752                 *p |= 0x04;
4753         ++p;
4754         *p++ = 1; /* reserved */
4755         int64val = (guint64*)p;
4756         *int64val++ = GUINT64_TO_LE (valid_mask);
4757         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4758         p += 16;
4759         int32val = (guint32*)p;
4760         for (i = 0; i < MONO_TABLE_NUM; i++){
4761                 if (meta->tables [i].rows == 0)
4762                         continue;
4763                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4764         }
4765         p = (unsigned char*)int32val;
4766
4767         /* sort the tables that still need sorting */
4768         table = &assembly->tables [MONO_TABLE_CONSTANT];
4769         if (table->rows)
4770                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4771         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4772         if (table->rows)
4773                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4774         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4775         if (table->rows)
4776                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4777         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4778         if (table->rows)
4779                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4780         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4781         if (table->rows)
4782                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4783         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4784         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4785         if (table->rows)
4786                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4787         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4788         if (table->rows)
4789                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4790
4791         /* compress the tables */
4792         for (i = 0; i < MONO_TABLE_NUM; i++){
4793                 int row, col;
4794                 guint32 *values;
4795                 guint32 bitfield = meta->tables [i].size_bitfield;
4796                 if (!meta->tables [i].rows)
4797                         continue;
4798                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4799                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4800                 meta->tables [i].base = (char*)p;
4801                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4802                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4803                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4804                                 switch (mono_metadata_table_size (bitfield, col)) {
4805                                 case 1:
4806                                         *p++ = values [col];
4807                                         break;
4808                                 case 2:
4809                                         *p++ = values [col] & 0xff;
4810                                         *p++ = (values [col] >> 8) & 0xff;
4811                                         break;
4812                                 case 4:
4813                                         *p++ = values [col] & 0xff;
4814                                         *p++ = (values [col] >> 8) & 0xff;
4815                                         *p++ = (values [col] >> 16) & 0xff;
4816                                         *p++ = (values [col] >> 24) & 0xff;
4817                                         break;
4818                                 default:
4819                                         g_assert_not_reached ();
4820                                 }
4821                         }
4822                 }
4823                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4824         }
4825         
4826         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4827         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4828         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4829         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4830         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4831
4832         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4833
4834         return TRUE;
4835 }
4836
4837 /*
4838  * Some tables in metadata need to be sorted according to some criteria, but
4839  * when methods and fields are first created with reflection, they may be assigned a token
4840  * that doesn't correspond to the final token they will get assigned after the sorting.
4841  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4842  * with the reflection objects that represent them. Once all the tables are set up, the 
4843  * reflection objects will contains the correct table index. fixup_method() will fixup the
4844  * tokens for the method with ILGenerator @ilgen.
4845  */
4846 static void
4847 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4848 {
4849         guint32 code_idx = GPOINTER_TO_UINT (value);
4850         MonoReflectionILTokenInfo *iltoken;
4851         MonoReflectionFieldBuilder *field;
4852         MonoReflectionCtorBuilder *ctor;
4853         MonoReflectionMethodBuilder *method;
4854         MonoReflectionTypeBuilder *tb;
4855         MonoReflectionArrayMethod *am;
4856         guint32 i, idx = 0;
4857         unsigned char *target;
4858
4859         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4860                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4861                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4862                 switch (target [3]) {
4863                 case MONO_TABLE_FIELD:
4864                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4865                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4866                                 idx = field->table_idx;
4867                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4868                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4869                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4870                         } else {
4871                                 g_assert_not_reached ();
4872                         }
4873                         break;
4874                 case MONO_TABLE_METHOD:
4875                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4876                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4877                                 idx = method->table_idx;
4878                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4879                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4880                                 idx = ctor->table_idx;
4881                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4882                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4883                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4884                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4885                         } else {
4886                                 g_assert_not_reached ();
4887                         }
4888                         break;
4889                 case MONO_TABLE_TYPEDEF:
4890                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4891                                 g_assert_not_reached ();
4892                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4893                         idx = tb->table_idx;
4894                         break;
4895                 case MONO_TABLE_MEMBERREF:
4896                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4897                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4898                                 idx = am->table_idx;
4899                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4900                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4901                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4902                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4903                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4904                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4905                                 continue;
4906                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4907                                 continue;
4908                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4909                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4910                                 g_assert (is_field_on_inst (f));
4911                                 continue;
4912                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4913                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4914                                 continue;
4915                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4916                                 continue;
4917                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4918                                 continue;
4919                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4920                                 continue;
4921                         } else {
4922                                 g_assert_not_reached ();
4923                         }
4924                         break;
4925                 case MONO_TABLE_METHODSPEC:
4926                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4927                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4928                                 g_assert (mono_method_signature (m)->generic_param_count);
4929                                 continue;
4930                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4931                                 continue;
4932                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4933                                 continue;
4934                         } else {
4935                                 g_assert_not_reached ();
4936                         }
4937                         break;
4938                 default:
4939                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4940                 }
4941                 target [0] = idx & 0xff;
4942                 target [1] = (idx >> 8) & 0xff;
4943                 target [2] = (idx >> 16) & 0xff;
4944         }
4945 }
4946
4947 /*
4948  * fixup_cattrs:
4949  *
4950  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4951  * value is not known when the table is emitted.
4952  */
4953 static void
4954 fixup_cattrs (MonoDynamicImage *assembly)
4955 {
4956         MonoDynamicTable *table;
4957         guint32 *values;
4958         guint32 type, i, idx, token;
4959         MonoObject *ctor;
4960
4961         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4962
4963         for (i = 0; i < table->rows; ++i) {
4964                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4965
4966                 type = values [MONO_CUSTOM_ATTR_TYPE];
4967                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4968                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4969                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4970                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4971                         g_assert (ctor);
4972
4973                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4974                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4975                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4976                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4977                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4978                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4979                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4980                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4981                         }
4982                 }
4983         }
4984 }
4985
4986 static gboolean
4987 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation, MonoError *error)
4988 {
4989         MonoDynamicTable *table;
4990         guint32 *values;
4991
4992         mono_error_init (error);
4993
4994         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4995         table->rows++;
4996         alloc_table (table, table->rows);
4997         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4998         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4999         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
5000         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name, error);
5001         return_val_if_nok (error, FALSE);
5002         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
5003         table->next_idx++;
5004         return TRUE;
5005 }
5006
5007 static gboolean
5008 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, MonoError *error)
5009 {
5010         MonoDynamicTable *table;
5011         guint32 *values;
5012         char blob_size [6];
5013         guchar hash [20];
5014         char *b = blob_size;
5015         char *name, *sname;
5016         guint32 idx, offset;
5017
5018         mono_error_init (error);
5019
5020         if (rsrc->filename) {
5021                 name = mono_string_to_utf8_checked (rsrc->filename, error);
5022                 return_val_if_nok (error, FALSE);
5023                 sname = g_path_get_basename (name);
5024         
5025                 table = &assembly->tables [MONO_TABLE_FILE];
5026                 table->rows++;
5027                 alloc_table (table, table->rows);
5028                 values = table->values + table->next_idx * MONO_FILE_SIZE;
5029                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
5030                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
5031                 g_free (sname);
5032
5033                 mono_sha1_get_digest_from_file (name, hash);
5034                 mono_metadata_encode_value (20, b, &b);
5035                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
5036                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
5037                 g_free (name);
5038                 idx = table->next_idx++;
5039                 rsrc->offset = 0;
5040                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
5041         } else {
5042                 char sizebuf [4];
5043                 char *data;
5044                 guint len;
5045                 if (rsrc->data) {
5046                         data = mono_array_addr (rsrc->data, char, 0);
5047                         len = mono_array_length (rsrc->data);
5048                 } else {
5049                         data = NULL;
5050                         len = 0;
5051                 }
5052                 offset = len;
5053                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
5054                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
5055                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
5056                 mono_image_add_stream_data (&assembly->resources, data, len);
5057
5058                 if (!mb->is_main)
5059                         /* 
5060                          * The entry should be emitted into the MANIFESTRESOURCE table of 
5061                          * the main module, but that needs to reference the FILE table
5062                          * which isn't emitted yet.
5063                          */
5064                         return TRUE;
5065                 else
5066                         idx = 0;
5067         }
5068
5069         return assembly_add_resource_manifest (mb, assembly, rsrc, idx, error);
5070 }
5071
5072 static gboolean
5073 set_version_from_string (MonoString *version, guint32 *values, MonoError *error)
5074 {
5075         gchar *ver, *p, *str;
5076         guint32 i;
5077         
5078         mono_error_init (error);
5079
5080         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5081         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5082         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5083         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5084         if (!version)
5085                 return TRUE;
5086         ver = str = mono_string_to_utf8_checked (version, error);
5087         return_val_if_nok (error, FALSE);
5088         for (i = 0; i < 4; ++i) {
5089                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5090                 switch (*p) {
5091                 case '.':
5092                         p++;
5093                         break;
5094                 case '*':
5095                         /* handle Revision and Build */
5096                         p++;
5097                         break;
5098                 }
5099                 ver = p;
5100         }
5101         g_free (str);
5102         return TRUE;
5103 }
5104
5105 static guint32
5106 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5107         gsize len;
5108         guint32 token = 0;
5109         char blob_size [6];
5110         char *b = blob_size;
5111
5112         if (!pkey)
5113                 return token;
5114
5115         len = mono_array_length (pkey);
5116         mono_metadata_encode_value (len, b, &b);
5117         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5118         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5119
5120         assembly->public_key = (guint8 *)g_malloc (len);
5121         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5122         assembly->public_key_len = len;
5123
5124         /* Special case: check for ECMA key (16 bytes) */
5125         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5126                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5127                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5128         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5129                 /* minimum key size (in 2.0) is 384 bits */
5130                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5131         } else {
5132                 /* FIXME - verifier */
5133                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5134                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5135         }
5136         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5137
5138         return token;
5139 }
5140
5141 static gboolean
5142 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5143 {
5144         MonoDynamicTable *table;
5145         MonoDynamicImage *assembly;
5146         MonoReflectionAssemblyBuilder *assemblyb;
5147         MonoDomain *domain;
5148         guint32 *values;
5149         int i;
5150         guint32 module_index;
5151
5152         mono_error_init (error);
5153
5154         assemblyb = moduleb->assemblyb;
5155         assembly = moduleb->dynamic_image;
5156         domain = mono_object_domain (assemblyb);
5157
5158         /* Emit ASSEMBLY table */
5159         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5160         alloc_table (table, 1);
5161         values = table->values + MONO_ASSEMBLY_SIZE;
5162         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5163         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name, error);
5164         return_val_if_nok (error, FALSE);
5165         if (assemblyb->culture) {
5166                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture, error);
5167                 return_val_if_nok (error, FALSE);
5168         } else {
5169                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5170         }
5171         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5172         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5173         if (!set_version_from_string (assemblyb->version, values, error))
5174                 return FALSE;
5175
5176         /* Emit FILE + EXPORTED_TYPE table */
5177         module_index = 0;
5178         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5179                 int j;
5180                 MonoReflectionModuleBuilder *file_module = 
5181                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5182                 if (file_module != moduleb) {
5183                         if (!mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly, error))
5184                                 return FALSE;
5185                         module_index ++;
5186                         if (file_module->types) {
5187                                 for (j = 0; j < file_module->num_types; ++j) {
5188                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5189                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5190                                         return_val_if_nok (error, FALSE);
5191                                 }
5192                         }
5193                 }
5194         }
5195         if (assemblyb->loaded_modules) {
5196                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5197                         MonoReflectionModule *file_module = 
5198                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5199                         if (!mono_image_fill_file_table (domain, file_module, assembly, error))
5200                                 return FALSE;
5201                         module_index ++;
5202                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5203                 }
5204         }
5205         if (assemblyb->type_forwarders)
5206                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5207
5208         /* Emit MANIFESTRESOURCE table */
5209         module_index = 0;
5210         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5211                 int j;
5212                 MonoReflectionModuleBuilder *file_module = 
5213                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5214                 /* The table for the main module is emitted later */
5215                 if (file_module != moduleb) {
5216                         module_index ++;
5217                         if (file_module->resources) {
5218                                 int len = mono_array_length (file_module->resources);
5219                                 for (j = 0; j < len; ++j) {
5220                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5221                                         if (!assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS), error))
5222                                                 return FALSE;
5223                                 }
5224                         }
5225                 }
5226         }
5227         return TRUE;
5228 }
5229
5230 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5231
5232 /*
5233  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5234  * for the modulebuilder @moduleb.
5235  * At the end of the process, method and field tokens are fixed up and the 
5236  * on-disk compressed metadata representation is created.
5237  * Return TRUE on success, or FALSE on failure and sets @error
5238  */
5239 gboolean
5240 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5241 {
5242         MonoDynamicTable *table;
5243         MonoDynamicImage *assembly;
5244         MonoReflectionAssemblyBuilder *assemblyb;
5245         MonoDomain *domain;
5246         MonoPtrArray types;
5247         guint32 *values;
5248         int i, j;
5249
5250         mono_error_init (error);
5251
5252         assemblyb = moduleb->assemblyb;
5253         assembly = moduleb->dynamic_image;
5254         domain = mono_object_domain (assemblyb);
5255
5256         if (assembly->text_rva)
5257                 return TRUE;
5258
5259         assembly->text_rva = START_TEXT_RVA;
5260
5261         if (moduleb->is_main) {
5262                 mono_image_emit_manifest (moduleb, error);
5263                 return_val_if_nok (error, FALSE);
5264         }
5265
5266         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5267         table->rows = 1; /* .<Module> */
5268         table->next_idx++;
5269         alloc_table (table, table->rows);
5270         /*
5271          * Set the first entry.
5272          */
5273         values = table->values + table->columns;
5274         values [MONO_TYPEDEF_FLAGS] = 0;
5275         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5276         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5277         values [MONO_TYPEDEF_EXTENDS] = 0;
5278         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5279         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5280
5281         /* 
5282          * handle global methods 
5283          * FIXME: test what to do when global methods are defined in multiple modules.
5284          */
5285         if (moduleb->global_methods) {
5286                 table = &assembly->tables [MONO_TABLE_METHOD];
5287                 table->rows += mono_array_length (moduleb->global_methods);
5288                 alloc_table (table, table->rows);
5289                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5290                         if (!mono_image_get_method_info (
5291                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5292                                 goto leave;
5293                 }
5294         }
5295         if (moduleb->global_fields) {
5296                 table = &assembly->tables [MONO_TABLE_FIELD];
5297                 table->rows += mono_array_length (moduleb->global_fields);
5298                 alloc_table (table, table->rows);
5299                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5300                         mono_image_get_field_info (
5301                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5302                                 error);
5303                         if (!is_ok (error))
5304                                 goto leave;
5305                 }
5306         }
5307
5308         table = &assembly->tables [MONO_TABLE_MODULE];
5309         alloc_table (table, 1);
5310         mono_image_fill_module_table (domain, moduleb, assembly, error);
5311         if (!is_ok (error))
5312                 goto leave;
5313
5314         /* Collect all types into a list sorted by their table_idx */
5315         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5316
5317         if (moduleb->types)
5318                 for (i = 0; i < moduleb->num_types; ++i) {
5319                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5320                         collect_types (&types, type);
5321                 }
5322
5323         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5324         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5325         table->rows += mono_ptr_array_size (types);
5326         alloc_table (table, table->rows);
5327
5328         /*
5329          * Emit type names + namespaces at one place inside the string heap,
5330          * so load_class_names () needs to touch fewer pages.
5331          */
5332         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5333                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5334                 string_heap_insert_mstring (&assembly->sheap, tb->nspace, error);
5335                 if (!is_ok (error))
5336                         goto leave_types;
5337         }
5338         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5339                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5340                 string_heap_insert_mstring (&assembly->sheap, tb->name, error);
5341                 if (!is_ok (error))
5342                         goto leave_types;
5343         }
5344
5345         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5346                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5347                 if (!mono_image_get_type_info (domain, type, assembly, error))
5348                         goto leave_types;
5349         }
5350
5351         /* 
5352          * table->rows is already set above and in mono_image_fill_module_table.
5353          */
5354         /* add all the custom attributes at the end, once all the indexes are stable */
5355         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5356                 goto leave_types;
5357
5358         /* CAS assembly permissions */
5359         if (assemblyb->permissions_minimum)
5360                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5361         if (assemblyb->permissions_optional)
5362                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5363         if (assemblyb->permissions_refused)
5364                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5365
5366         if (!module_add_cattrs (assembly, moduleb, error))
5367                 goto leave_types;
5368
5369         /* fixup tokens */
5370         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5371
5372         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5373          * the final tokens and don't need another fixup pass. */
5374
5375         if (moduleb->global_methods) {
5376                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5377                         MonoReflectionMethodBuilder *mb = mono_array_get (
5378                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5379                         if (!mono_image_add_methodimpl (assembly, mb, error))
5380                                 goto leave_types;
5381                 }
5382         }
5383
5384         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5385                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5386                 if (type->methods) {
5387                         for (j = 0; j < type->num_methods; ++j) {
5388                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5389                                         type->methods, MonoReflectionMethodBuilder*, j);
5390
5391                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5392                                         goto leave_types;
5393                         }
5394                 }
5395         }
5396
5397         fixup_cattrs (assembly);
5398
5399 leave_types:
5400         mono_ptr_array_destroy (types);
5401 leave:
5402
5403         return mono_error_ok (error);
5404 }
5405
5406 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5407
5408 gboolean
5409 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5410 {
5411         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5412 }
5413
5414 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5415
5416
5417 typedef struct {
5418         guint32 import_lookup_table;
5419         guint32 timestamp;
5420         guint32 forwarder;
5421         guint32 name_rva;
5422         guint32 import_address_table_rva;
5423 } MonoIDT;
5424
5425 typedef struct {
5426         guint32 name_rva;
5427         guint32 flags;
5428 } MonoILT;
5429
5430 #ifndef DISABLE_REFLECTION_EMIT
5431
5432 /*
5433  * mono_image_insert_string:
5434  * @module: module builder object
5435  * @str: a string
5436  *
5437  * Insert @str into the user string stream of @module.
5438  */
5439 guint32
5440 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5441 {
5442         MonoDynamicImage *assembly;
5443         guint32 idx;
5444         char buf [16];
5445         char *b = buf;
5446         
5447         if (!module->dynamic_image)
5448                 mono_image_module_basic_init (module);
5449
5450         assembly = module->dynamic_image;
5451         
5452         if (assembly->save) {
5453                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5454                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5455 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5456         {
5457                 char *swapped = g_malloc (2 * mono_string_length (str));
5458                 const char *p = (const char*)mono_string_chars (str);
5459
5460                 swap_with_size (swapped, p, 2, mono_string_length (str));
5461                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5462                 g_free (swapped);
5463         }
5464 #else
5465                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5466 #endif
5467                 mono_image_add_stream_data (&assembly->us, "", 1);
5468         } else {
5469                 idx = assembly->us.index ++;
5470         }
5471
5472         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5473
5474         return MONO_TOKEN_STRING | idx;
5475 }
5476
5477 guint32
5478 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5479 {
5480         MonoClass *klass;
5481         guint32 token = 0;
5482         MonoMethodSignature *sig;
5483
5484         mono_error_init (error);
5485
5486         klass = obj->vtable->klass;
5487         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5488                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5489                 MonoMethodSignature *old;
5490                 guint32 sig_token, parent;
5491                 int nargs, i;
5492
5493                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5494
5495                 nargs = mono_array_length (opt_param_types);
5496                 old = mono_method_signature (method);
5497                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5498
5499                 sig->hasthis = old->hasthis;
5500                 sig->explicit_this = old->explicit_this;
5501                 sig->call_convention = old->call_convention;
5502                 sig->generic_param_count = old->generic_param_count;
5503                 sig->param_count = old->param_count + nargs;
5504                 sig->sentinelpos = old->param_count;
5505                 sig->ret = old->ret;
5506
5507                 for (i = 0; i < old->param_count; i++)
5508                         sig->params [i] = old->params [i];
5509
5510                 for (i = 0; i < nargs; i++) {
5511                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5512                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5513                         if (!is_ok (error)) goto fail;
5514                 }
5515
5516                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5517                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5518                 parent >>= MONO_TYPEDEFORREF_BITS;
5519
5520                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5521                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5522
5523                 sig_token = method_encode_signature (assembly, sig);
5524                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5525         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5526                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5527                 ReflectionMethodBuilder rmb;
5528                 guint32 parent, sig_token;
5529                 int nopt_args, nparams, ngparams, i;
5530
5531                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5532                         goto fail;
5533                 
5534                 rmb.opt_types = opt_param_types;
5535                 nopt_args = mono_array_length (opt_param_types);
5536
5537                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5538                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5539                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5540
5541                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5542                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5543                 sig->call_convention = rmb.call_conv;
5544                 sig->generic_param_count = ngparams;
5545                 sig->param_count = nparams + nopt_args;
5546                 sig->sentinelpos = nparams;
5547                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5548                 if (!is_ok (error)) goto fail;
5549
5550                 for (i = 0; i < nparams; i++) {
5551                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5552                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5553                         if (!is_ok (error)) goto fail;
5554                 }
5555
5556                 for (i = 0; i < nopt_args; i++) {
5557                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5558                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5559                         if (!is_ok (error)) goto fail;
5560                 }
5561
5562                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5563                 if (!is_ok (error))
5564                         goto fail;
5565
5566                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5567                 if (!mono_error_ok (error))
5568                         goto fail;
5569                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5570
5571                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5572                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5573
5574                 char *name = mono_string_to_utf8_checked (rmb.name, error);
5575                 if (!is_ok (error)) goto fail;
5576                 token = mono_image_get_varargs_method_token (
5577                         assembly, parent, name, sig_token);
5578                 g_free (name);
5579         } else {
5580                 g_error ("requested method token for %s\n", klass->name);
5581         }
5582
5583         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5584         register_dyn_token (assembly, token, obj);
5585         return token;
5586 fail:
5587         g_assert (!mono_error_ok (error));
5588         return 0;
5589 }
5590
5591 /*
5592  * mono_image_create_token:
5593  * @assembly: a dynamic assembly
5594  * @obj:
5595  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5596  *
5597  * Get a token to insert in the IL code stream for the given MemberInfo.
5598  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5599  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5600  * entry.
5601  */
5602 guint32
5603 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5604                          gboolean create_open_instance, gboolean register_token,
5605                          MonoError *error)
5606 {
5607         MonoClass *klass;
5608         guint32 token = 0;
5609
5610         mono_error_init (error);
5611
5612         klass = obj->vtable->klass;
5613
5614         /* Check for user defined reflection objects */
5615         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5616         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5617                 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5618                 return 0;
5619         }
5620
5621         if (strcmp (klass->name, "MethodBuilder") == 0) {
5622                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5623                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5624
5625                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5626                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5627                 else {
5628                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5629                         if (!mono_error_ok (error))
5630                                 return 0;
5631                 }
5632                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5633         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5634                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5635                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5636
5637                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5638                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5639                 else {
5640                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5641                         if (!mono_error_ok (error))
5642                                 return 0;
5643                 }
5644                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5645         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5646                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5647                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5648                 if (tb->generic_params) {
5649                         token = mono_image_get_generic_field_token (assembly, fb, error);
5650                         return_val_if_nok (error, 0);
5651                 } else {
5652                         if (tb->module->dynamic_image == assembly) {
5653                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5654                         } else {
5655                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5656                         }
5657                 }
5658         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5659                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5660                 if (create_open_instance && tb->generic_params) {
5661                         MonoType *type;
5662                         init_type_builder_generics (obj, error);
5663                         return_val_if_nok (error, 0);
5664                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5665                         return_val_if_nok (error, 0);
5666                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5667                         token = mono_metadata_token_from_dor (token);
5668                 } else if (tb->module->dynamic_image == assembly) {
5669                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5670                 } else {
5671                         MonoType *type;
5672                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5673                         return_val_if_nok (error, 0);
5674                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5675                 }
5676         } else if (strcmp (klass->name, "RuntimeType") == 0) {
5677                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5678                 return_val_if_nok (error, 0);
5679                 MonoClass *mc = mono_class_from_mono_type (type);
5680                 token = mono_metadata_token_from_dor (
5681                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5682         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5683                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5684                 return_val_if_nok (error, 0);
5685                 token = mono_metadata_token_from_dor (
5686                         mono_image_typedef_or_ref (assembly, type));
5687         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5688                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5689                 return_val_if_nok (error, 0);
5690                 token = mono_metadata_token_from_dor (
5691                         mono_image_typedef_or_ref (assembly, type));
5692         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5693                    strcmp (klass->name, "MonoMethod") == 0 ||
5694                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5695                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5696                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5697                 if (m->method->is_inflated) {
5698                         if (create_open_instance)
5699                                 token = mono_image_get_methodspec_token (assembly, m->method);
5700                         else
5701                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5702                 } else if ((m->method->klass->image == &assembly->image) &&
5703                          !m->method->klass->generic_class) {
5704                         static guint32 method_table_idx = 0xffffff;
5705                         if (m->method->klass->wastypebuilder) {
5706                                 /* we use the same token as the one that was assigned
5707                                  * to the Methodbuilder.
5708                                  * FIXME: do the equivalent for Fields.
5709                                  */
5710                                 token = m->method->token;
5711                         } else {
5712                                 /*
5713                                  * Each token should have a unique index, but the indexes are
5714                                  * assigned by managed code, so we don't know about them. An
5715                                  * easy solution is to count backwards...
5716                                  */
5717                                 method_table_idx --;
5718                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5719                         }
5720                 } else {
5721                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5722                 }
5723                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5724         } else if (strcmp (klass->name, "MonoField") == 0) {
5725                 MonoReflectionField *f = (MonoReflectionField *)obj;
5726                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5727                         static guint32 field_table_idx = 0xffffff;
5728                         field_table_idx --;
5729                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5730                 } else {
5731                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5732                 }
5733                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5734         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5735                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5736                 token = mono_image_get_array_token (assembly, m, error);
5737                 return_val_if_nok (error, 0);
5738         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5739                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5740                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5741                 return_val_if_nok (error, 0);
5742         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5743                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5744                 return_val_if_nok (error, 0);
5745                 token = mono_metadata_token_from_dor (
5746                         mono_image_typedef_or_ref (assembly, type));
5747         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5748                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5749                 token = mono_image_get_field_on_inst_token (assembly, f, error);
5750                 return_val_if_nok (error, 0);
5751         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5752                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5753                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5754                 if (!mono_error_ok (error))
5755                         return 0;
5756         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5757                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5758                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5759                 if (!mono_error_ok (error))
5760                         return 0;
5761         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5762                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5763                 return_val_if_nok (error, 0);
5764                 token = mono_metadata_token_from_dor (
5765                                 mono_image_typedef_or_ref (assembly, type));
5766         } else {
5767                 g_error ("requested token for %s\n", klass->name);
5768         }
5769
5770         if (register_token)
5771                 mono_image_register_token (assembly, token, obj);
5772
5773         return token;
5774 }
5775
5776 /*
5777  * mono_image_register_token:
5778  *
5779  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5780  * the Module.ResolveXXXToken () methods to work.
5781  */
5782 void
5783 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5784 {
5785         MonoObject *prev;
5786
5787         dynamic_image_lock (assembly);
5788         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5789         if (prev) {
5790                 /* There could be multiple MethodInfo objects with the same token */
5791                 //g_assert (prev == obj);
5792         } else {
5793                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5794         }
5795         dynamic_image_unlock (assembly);
5796 }
5797
5798 static MonoDynamicImage*
5799 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5800 {
5801         static const guchar entrycode [16] = {0xff, 0x25, 0};
5802         MonoDynamicImage *image;
5803         int i;
5804
5805         const char *version;
5806
5807         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5808                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5809         else
5810                 version = mono_get_runtime_info ()->runtime_version;
5811
5812 #if HAVE_BOEHM_GC
5813         /* The MonoGHashTable's need GC tracking */
5814         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5815 #else
5816         image = g_new0 (MonoDynamicImage, 1);
5817 #endif
5818
5819         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5820         
5821         /*g_print ("created image %p\n", image);*/
5822         /* keep in sync with image.c */
5823         image->image.name = assembly_name;
5824         image->image.assembly_name = image->image.name; /* they may be different */
5825         image->image.module_name = module_name;
5826         image->image.version = g_strdup (version);
5827         image->image.md_version_major = 1;
5828         image->image.md_version_minor = 1;
5829         image->image.dynamic = TRUE;
5830
5831         image->image.references = g_new0 (MonoAssembly*, 1);
5832         image->image.references [0] = NULL;
5833
5834         mono_image_init (&image->image);
5835
5836         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5837         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5838         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5839         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5840         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5841         image->handleref = g_hash_table_new (NULL, NULL);
5842         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5843         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5844         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5845         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5846         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5847         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5848         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5849         image->gen_params = g_ptr_array_new ();
5850         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5851
5852         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5853         string_heap_init (&image->sheap);
5854         mono_image_add_stream_data (&image->us, "", 1);
5855         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5856         /* import tables... */
5857         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5858         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5859         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5860         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5861         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5862         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5863         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5864         stream_data_align (&image->code);
5865
5866         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5867
5868         for (i=0; i < MONO_TABLE_NUM; ++i) {
5869                 image->tables [i].next_idx = 1;
5870                 image->tables [i].columns = table_sizes [i];
5871         }
5872
5873         image->image.assembly = (MonoAssembly*)assembly;
5874         image->run = assembly->run;
5875         image->save = assembly->save;
5876         image->pe_kind = 0x1; /* ILOnly */
5877         image->machine = 0x14c; /* I386 */
5878         
5879         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5880
5881         dynamic_images_lock ();
5882
5883         if (!dynamic_images)
5884                 dynamic_images = g_ptr_array_new ();
5885
5886         g_ptr_array_add (dynamic_images, image);
5887
5888         dynamic_images_unlock ();
5889
5890         return image;
5891 }
5892 #endif
5893
5894 static void
5895 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5896 {
5897         g_free (key);
5898 }
5899
5900 static void
5901 release_hashtable (MonoGHashTable **hash)
5902 {
5903         if (*hash) {
5904                 mono_g_hash_table_destroy (*hash);
5905                 *hash = NULL;
5906         }
5907 }
5908
5909 void
5910 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5911 {
5912         release_hashtable (&image->token_fixups);
5913         release_hashtable (&image->handleref_managed);
5914         release_hashtable (&image->tokens);
5915         release_hashtable (&image->remapped_tokens);
5916         release_hashtable (&image->generic_def_objects);
5917         release_hashtable (&image->methodspec);
5918 }
5919
5920 // Free dynamic image pass one: Free resources but not image itself
5921 void
5922 mono_dynamic_image_free (MonoDynamicImage *image)
5923 {
5924         MonoDynamicImage *di = image;
5925         GList *list;
5926         int i;
5927
5928         if (di->methodspec)
5929                 mono_g_hash_table_destroy (di->methodspec);
5930         if (di->typespec)
5931                 g_hash_table_destroy (di->typespec);
5932         if (di->typeref)
5933                 g_hash_table_destroy (di->typeref);
5934         if (di->handleref)
5935                 g_hash_table_destroy (di->handleref);
5936         if (di->handleref_managed)
5937                 mono_g_hash_table_destroy (di->handleref_managed);
5938         if (di->tokens)
5939                 mono_g_hash_table_destroy (di->tokens);
5940         if (di->remapped_tokens)
5941                 mono_g_hash_table_destroy (di->remapped_tokens);
5942         if (di->generic_def_objects)
5943                 mono_g_hash_table_destroy (di->generic_def_objects);
5944         if (di->blob_cache) {
5945                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5946                 g_hash_table_destroy (di->blob_cache);
5947         }
5948         if (di->standalonesig_cache)
5949                 g_hash_table_destroy (di->standalonesig_cache);
5950         for (list = di->array_methods; list; list = list->next) {
5951                 ArrayMethod *am = (ArrayMethod *)list->data;
5952                 g_free (am->sig);
5953                 g_free (am->name);
5954                 g_free (am);
5955         }
5956         g_list_free (di->array_methods);
5957         if (di->gen_params) {
5958                 for (i = 0; i < di->gen_params->len; i++) {
5959                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5960                         mono_gc_deregister_root ((char*) &entry->gparam);
5961                         g_free (entry);
5962                 }
5963                 g_ptr_array_free (di->gen_params, TRUE);
5964         }
5965         if (di->token_fixups)
5966                 mono_g_hash_table_destroy (di->token_fixups);
5967         if (di->method_to_table_idx)
5968                 g_hash_table_destroy (di->method_to_table_idx);
5969         if (di->field_to_table_idx)
5970                 g_hash_table_destroy (di->field_to_table_idx);
5971         if (di->method_aux_hash)
5972                 g_hash_table_destroy (di->method_aux_hash);
5973         if (di->vararg_aux_hash)
5974                 g_hash_table_destroy (di->vararg_aux_hash);
5975         g_free (di->strong_name);
5976         g_free (di->win32_res);
5977         if (di->public_key)
5978                 g_free (di->public_key);
5979
5980         /*g_print ("string heap destroy for image %p\n", di);*/
5981         mono_dynamic_stream_reset (&di->sheap);
5982         mono_dynamic_stream_reset (&di->code);
5983         mono_dynamic_stream_reset (&di->resources);
5984         mono_dynamic_stream_reset (&di->us);
5985         mono_dynamic_stream_reset (&di->blob);
5986         mono_dynamic_stream_reset (&di->tstream);
5987         mono_dynamic_stream_reset (&di->guid);
5988         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5989                 g_free (di->tables [i].values);
5990         }
5991
5992         dynamic_images_lock ();
5993
5994         if (dynamic_images)
5995                 g_ptr_array_remove (dynamic_images, di);
5996
5997         dynamic_images_unlock ();
5998 }
5999
6000 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
6001 void
6002 mono_dynamic_image_free_image (MonoDynamicImage *image)
6003 {
6004         /* See create_dynamic_mono_image () */
6005 #if HAVE_BOEHM_GC
6006         /* Allocated using GC_MALLOC */
6007 #else
6008         g_free (image);
6009 #endif
6010 }
6011
6012 #ifndef DISABLE_REFLECTION_EMIT
6013
6014 /*
6015  * mono_image_basic_init:
6016  * @assembly: an assembly builder object
6017  *
6018  * Create the MonoImage that represents the assembly builder and setup some
6019  * of the helper hash table and the basic metadata streams.
6020  */
6021 void
6022 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
6023 {
6024         MonoError error;
6025         MonoDynamicAssembly *assembly;
6026         MonoDynamicImage *image;
6027         MonoDomain *domain = mono_object_domain (assemblyb);
6028         
6029         if (assemblyb->dynamic_assembly)
6030                 return;
6031
6032 #if HAVE_BOEHM_GC
6033         /* assembly->assembly.image might be GC allocated */
6034         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
6035 #else
6036         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
6037 #endif
6038
6039         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
6040         
6041         assembly->assembly.ref_count = 1;
6042         assembly->assembly.dynamic = TRUE;
6043         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
6044         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
6045         assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
6046         if (mono_error_set_pending_exception (&error))
6047                 return;
6048         if (assemblyb->culture) {
6049                 assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
6050                 if (mono_error_set_pending_exception (&error))
6051                         return;
6052         } else
6053                 assembly->assembly.aname.culture = g_strdup ("");
6054
6055         if (assemblyb->version) {
6056                         char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
6057                         if (mono_error_set_pending_exception (&error))
6058                                 return;
6059                         char **version = g_strsplit (vstr, ".", 4);
6060                         char **parts = version;
6061                         assembly->assembly.aname.major = atoi (*parts++);
6062                         assembly->assembly.aname.minor = atoi (*parts++);
6063                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
6064                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
6065
6066                         g_strfreev (version);
6067                         g_free (vstr);
6068         } else {
6069                         assembly->assembly.aname.major = 0;
6070                         assembly->assembly.aname.minor = 0;
6071                         assembly->assembly.aname.build = 0;
6072                         assembly->assembly.aname.revision = 0;
6073         }
6074
6075         assembly->run = assemblyb->access != 2;
6076         assembly->save = assemblyb->access != 1;
6077         assembly->domain = domain;
6078
6079         char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
6080         if (mono_error_set_pending_exception (&error))
6081                 return;
6082         image = create_dynamic_mono_image (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
6083         image->initial_image = TRUE;
6084         assembly->assembly.aname.name = image->image.name;
6085         assembly->assembly.image = &image->image;
6086         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
6087                 /* -1 to correct for the trailing NULL byte */
6088                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
6089                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6090                 }
6091                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
6092         }
6093
6094         mono_domain_assemblies_lock (domain);
6095         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6096         mono_domain_assemblies_unlock (domain);
6097
6098         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6099         
6100         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6101         
6102         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6103 }
6104
6105 #endif /* !DISABLE_REFLECTION_EMIT */
6106
6107 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6108
6109 static int
6110 calc_section_size (MonoDynamicImage *assembly)
6111 {
6112         int nsections = 0;
6113
6114         /* alignment constraints */
6115         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6116         g_assert ((assembly->code.index % 4) == 0);
6117         assembly->meta_size += 3;
6118         assembly->meta_size &= ~3;
6119         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6120         g_assert ((assembly->resources.index % 4) == 0);
6121
6122         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6123         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6124         nsections++;
6125
6126         if (assembly->win32_res) {
6127                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6128
6129                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6130                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6131                 nsections++;
6132         }
6133
6134         assembly->sections [MONO_SECTION_RELOC].size = 12;
6135         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6136         nsections++;
6137
6138         return nsections;
6139 }
6140
6141 typedef struct {
6142         guint32 id;
6143         guint32 offset;
6144         GSList *children;
6145         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6146 } ResTreeNode;
6147
6148 static int
6149 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6150 {
6151         ResTreeNode *t1 = (ResTreeNode*)a;
6152         ResTreeNode *t2 = (ResTreeNode*)b;
6153
6154         return t1->id - t2->id;
6155 }
6156
6157 /*
6158  * resource_tree_create:
6159  *
6160  *  Organize the resources into a resource tree.
6161  */
6162 static ResTreeNode *
6163 resource_tree_create (MonoArray *win32_resources)
6164 {
6165         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6166         GSList *l;
6167         int i;
6168
6169         tree = g_new0 (ResTreeNode, 1);
6170         
6171         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6172                 MonoReflectionWin32Resource *win32_res =
6173                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6174
6175                 /* Create node */
6176
6177                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6178                 lang_node = g_new0 (ResTreeNode, 1);
6179                 lang_node->id = win32_res->lang_id;
6180                 lang_node->win32_res = win32_res;
6181
6182                 /* Create type node if neccesary */
6183                 type_node = NULL;
6184                 for (l = tree->children; l; l = l->next)
6185                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6186                                 type_node = (ResTreeNode*)l->data;
6187                                 break;
6188                         }
6189
6190                 if (!type_node) {
6191                         type_node = g_new0 (ResTreeNode, 1);
6192                         type_node->id = win32_res->res_type;
6193
6194                         /* 
6195                          * The resource types have to be sorted otherwise
6196                          * Windows Explorer can't display the version information.
6197                          */
6198                         tree->children = g_slist_insert_sorted (tree->children, 
6199                                 type_node, resource_tree_compare_by_id);
6200                 }
6201
6202                 /* Create res node if neccesary */
6203                 res_node = NULL;
6204                 for (l = type_node->children; l; l = l->next)
6205                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6206                                 res_node = (ResTreeNode*)l->data;
6207                                 break;
6208                         }
6209
6210                 if (!res_node) {
6211                         res_node = g_new0 (ResTreeNode, 1);
6212                         res_node->id = win32_res->res_id;
6213                         type_node->children = g_slist_append (type_node->children, res_node);
6214                 }
6215
6216                 res_node->children = g_slist_append (res_node->children, lang_node);
6217         }
6218
6219         return tree;
6220 }
6221
6222 /*
6223  * resource_tree_encode:
6224  * 
6225  *   Encode the resource tree into the format used in the PE file.
6226  */
6227 static void
6228 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6229 {
6230         char *entries;
6231         MonoPEResourceDir dir;
6232         MonoPEResourceDirEntry dir_entry;
6233         MonoPEResourceDataEntry data_entry;
6234         GSList *l;
6235         guint32 res_id_entries;
6236
6237         /*
6238          * For the format of the resource directory, see the article
6239          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6240          * Matt Pietrek
6241          */
6242
6243         memset (&dir, 0, sizeof (dir));
6244         memset (&dir_entry, 0, sizeof (dir_entry));
6245         memset (&data_entry, 0, sizeof (data_entry));
6246
6247         g_assert (sizeof (dir) == 16);
6248         g_assert (sizeof (dir_entry) == 8);
6249         g_assert (sizeof (data_entry) == 16);
6250
6251         node->offset = p - begin;
6252
6253         /* IMAGE_RESOURCE_DIRECTORY */
6254         res_id_entries = g_slist_length (node->children);
6255         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6256
6257         memcpy (p, &dir, sizeof (dir));
6258         p += sizeof (dir);
6259
6260         /* Reserve space for entries */
6261         entries = p;
6262         p += sizeof (dir_entry) * res_id_entries;
6263
6264         /* Write children */
6265         for (l = node->children; l; l = l->next) {
6266                 ResTreeNode *child = (ResTreeNode*)l->data;
6267
6268                 if (child->win32_res) {
6269                         guint32 size;
6270
6271                         child->offset = p - begin;
6272
6273                         /* IMAGE_RESOURCE_DATA_ENTRY */
6274                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6275                         size = mono_array_length (child->win32_res->res_data);
6276                         data_entry.rde_size = GUINT32_TO_LE (size);
6277
6278                         memcpy (p, &data_entry, sizeof (data_entry));
6279                         p += sizeof (data_entry);
6280
6281                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6282                         p += size;
6283                 } else {
6284                         resource_tree_encode (child, begin, p, &p);
6285                 }
6286         }
6287
6288         /* IMAGE_RESOURCE_ENTRY */
6289         for (l = node->children; l; l = l->next) {
6290                 ResTreeNode *child = (ResTreeNode*)l->data;
6291
6292                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6293                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6294
6295                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6296                 entries += sizeof (dir_entry);
6297         }
6298
6299         *endbuf = p;
6300 }
6301
6302 static void
6303 resource_tree_free (ResTreeNode * node)
6304 {
6305         GSList * list;
6306         for (list = node->children; list; list = list->next)
6307                 resource_tree_free ((ResTreeNode*)list->data);
6308         g_slist_free(node->children);
6309         g_free (node);
6310 }
6311
6312 static void
6313 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6314 {
6315         char *buf;
6316         char *p;
6317         guint32 size, i;
6318         MonoReflectionWin32Resource *win32_res;
6319         ResTreeNode *tree;
6320
6321         if (!assemblyb->win32_resources)
6322                 return;
6323
6324         /*
6325          * Resources are stored in a three level tree inside the PE file.
6326          * - level one contains a node for each type of resource
6327          * - level two contains a node for each resource
6328          * - level three contains a node for each instance of a resource for a
6329          *   specific language.
6330          */
6331
6332         tree = resource_tree_create (assemblyb->win32_resources);
6333
6334         /* Estimate the size of the encoded tree */
6335         size = 0;
6336         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6337                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6338                 size += mono_array_length (win32_res->res_data);
6339         }
6340         /* Directory structure */
6341         size += mono_array_length (assemblyb->win32_resources) * 256;
6342         p = buf = (char *)g_malloc (size);
6343
6344         resource_tree_encode (tree, p, p, &p);
6345
6346         g_assert (p - buf <= size);
6347
6348         assembly->win32_res = (char *)g_malloc (p - buf);
6349         assembly->win32_res_size = p - buf;
6350         memcpy (assembly->win32_res, buf, p - buf);
6351
6352         g_free (buf);
6353         resource_tree_free (tree);
6354 }
6355
6356 static void
6357 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6358 {
6359         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6360         int i;
6361
6362         p += sizeof (MonoPEResourceDir);
6363         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6364                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6365                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6366                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6367                         fixup_resource_directory (res_section, child, rva);
6368                 } else {
6369                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6370                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6371                 }
6372
6373                 p += sizeof (MonoPEResourceDirEntry);
6374         }
6375 }
6376
6377 static void
6378 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6379 {
6380         guint32 dummy;
6381         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6382                 g_error ("WriteFile returned %d\n", GetLastError ());
6383 }
6384
6385 /*
6386  * mono_image_create_pefile:
6387  * @mb: a module builder object
6388  * 
6389  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6390  * assembly->pefile where it can be easily retrieved later in chunks.
6391  */
6392 gboolean
6393 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6394 {
6395         MonoMSDOSHeader *msdos;
6396         MonoDotNetHeader *header;
6397         MonoSectionTable *section;
6398         MonoCLIHeader *cli_header;
6399         guint32 size, image_size, virtual_base, text_offset;
6400         guint32 header_start, section_start, file_offset, virtual_offset;
6401         MonoDynamicImage *assembly;
6402         MonoReflectionAssemblyBuilder *assemblyb;
6403         MonoDynamicStream pefile_stream = {0};
6404         MonoDynamicStream *pefile = &pefile_stream;
6405         int i, nsections;
6406         guint32 *rva, value;
6407         guchar *p;
6408         static const unsigned char msheader[] = {
6409                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6410                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6411                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6412                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6413                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6414                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6415                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6416                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6417         };
6418
6419         mono_error_init (error);
6420
6421         assemblyb = mb->assemblyb;
6422
6423         mono_image_basic_init (assemblyb);
6424         assembly = mb->dynamic_image;
6425
6426         assembly->pe_kind = assemblyb->pe_kind;
6427         assembly->machine = assemblyb->machine;
6428         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6429         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6430         
6431         if (!mono_image_build_metadata (mb, error))
6432                 return FALSE;
6433         
6434
6435         if (mb->is_main && assemblyb->resources) {
6436                 int len = mono_array_length (assemblyb->resources);
6437                 for (i = 0; i < len; ++i) {
6438                         if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i), error))
6439                                 return FALSE;
6440                 }
6441         }
6442
6443         if (mb->resources) {
6444                 int len = mono_array_length (mb->resources);
6445                 for (i = 0; i < len; ++i) {
6446                         if (!assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i), error))
6447                                 return FALSE;
6448                 }
6449         }
6450
6451         if (!build_compressed_metadata (assembly, error))
6452                 return FALSE;
6453
6454         if (mb->is_main)
6455                 assembly_add_win32_resources (assembly, assemblyb);
6456
6457         nsections = calc_section_size (assembly);
6458         
6459         /* The DOS header and stub */
6460         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6461         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6462
6463         /* the dotnet header */
6464         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6465
6466         /* the section tables */
6467         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6468
6469         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6470         virtual_offset = VIRT_ALIGN;
6471         image_size = 0;
6472
6473         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6474                 if (!assembly->sections [i].size)
6475                         continue;
6476                 /* align offsets */
6477                 file_offset += FILE_ALIGN - 1;
6478                 file_offset &= ~(FILE_ALIGN - 1);
6479                 virtual_offset += VIRT_ALIGN - 1;
6480                 virtual_offset &= ~(VIRT_ALIGN - 1);
6481
6482                 assembly->sections [i].offset = file_offset;
6483                 assembly->sections [i].rva = virtual_offset;
6484
6485                 file_offset += assembly->sections [i].size;
6486                 virtual_offset += assembly->sections [i].size;
6487                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6488         }
6489
6490         file_offset += FILE_ALIGN - 1;
6491         file_offset &= ~(FILE_ALIGN - 1);
6492
6493         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6494
6495         /* back-patch info */
6496         msdos = (MonoMSDOSHeader*)pefile->data;
6497         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6498
6499         header = (MonoDotNetHeader*)(pefile->data + header_start);
6500         header->pesig [0] = 'P';
6501         header->pesig [1] = 'E';
6502         
6503         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6504         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6505         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6506         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6507         if (assemblyb->pekind == 1) {
6508                 /* it's a dll */
6509                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6510         } else {
6511                 /* it's an exe */
6512                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6513         }
6514
6515         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6516
6517         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6518         header->pe.pe_major = 6;
6519         header->pe.pe_minor = 0;
6520         size = assembly->sections [MONO_SECTION_TEXT].size;
6521         size += FILE_ALIGN - 1;
6522         size &= ~(FILE_ALIGN - 1);
6523         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6524         size = assembly->sections [MONO_SECTION_RSRC].size;
6525         size += FILE_ALIGN - 1;
6526         size &= ~(FILE_ALIGN - 1);
6527         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6528         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6529         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6530         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6531         /* pe_rva_entry_point always at the beginning of the text section */
6532         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6533
6534         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6535         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6536         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6537         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6538         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6539         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6540         size = section_start;
6541         size += FILE_ALIGN - 1;
6542         size &= ~(FILE_ALIGN - 1);
6543         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6544         size = image_size;
6545         size += VIRT_ALIGN - 1;
6546         size &= ~(VIRT_ALIGN - 1);
6547         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6548
6549         /*
6550         // Translate the PEFileKind value to the value expected by the Windows loader
6551         */
6552         {
6553                 short kind;
6554
6555                 /*
6556                 // PEFileKinds.Dll == 1
6557                 // PEFileKinds.ConsoleApplication == 2
6558                 // PEFileKinds.WindowApplication == 3
6559                 //
6560                 // need to get:
6561                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6562                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6563                 */
6564                 if (assemblyb->pekind == 3)
6565                         kind = 2;
6566                 else
6567                         kind = 3;
6568                 
6569                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6570         }    
6571         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6572         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6573         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6574         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6575         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6576         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6577
6578         /* fill data directory entries */
6579
6580         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6581         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6582
6583         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6584         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6585
6586         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6587         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6588         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6589         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6590         /* patch entrypoint name */
6591         if (assemblyb->pekind == 1)
6592                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6593         else
6594                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6595         /* patch imported function RVA name */
6596         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6597         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6598
6599         /* the import table */
6600         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6601         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6602         /* patch imported dll RVA name and other entries in the dir */
6603         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6604         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6605         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6606         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6607         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6608         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6609
6610         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6611         value = (assembly->text_rva + assembly->imp_names_offset);
6612         *p++ = (value) & 0xff;
6613         *p++ = (value >> 8) & (0xff);
6614         *p++ = (value >> 16) & (0xff);
6615         *p++ = (value >> 24) & (0xff);
6616
6617         /* the CLI header info */
6618         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6619         cli_header->ch_size = GUINT32_FROM_LE (72);
6620         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6621         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6622         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6623         if (assemblyb->entry_point) {
6624                 guint32 table_idx = 0;
6625                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6626                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6627                         table_idx = methodb->table_idx;
6628                 } else {
6629                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6630                 }
6631                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6632         } else {
6633                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6634         }
6635         /* The embedded managed resources */
6636         text_offset = assembly->text_rva + assembly->code.index;
6637         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6638         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6639         text_offset += assembly->resources.index;
6640         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6641         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6642         text_offset += assembly->meta_size;
6643         if (assembly->strong_name_size) {
6644                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6645                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6646                 text_offset += assembly->strong_name_size;
6647         }
6648
6649         /* write the section tables and section content */
6650         section = (MonoSectionTable*)(pefile->data + section_start);
6651         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6652                 static const char section_names [][7] = {
6653                         ".text", ".rsrc", ".reloc"
6654                 };
6655                 if (!assembly->sections [i].size)
6656                         continue;
6657                 strcpy (section->st_name, section_names [i]);
6658                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6659                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6660                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6661                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6662                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6663                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6664                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6665                 section ++;
6666         }
6667         
6668         checked_write_file (file, pefile->data, pefile->index);
6669         
6670         mono_dynamic_stream_reset (pefile);
6671         
6672         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6673                 if (!assembly->sections [i].size)
6674                         continue;
6675                 
6676                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6677                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6678                 
6679                 switch (i) {
6680                 case MONO_SECTION_TEXT:
6681                         /* patch entry point */
6682                         p = (guchar*)(assembly->code.data + 2);
6683                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6684                         *p++ = (value) & 0xff;
6685                         *p++ = (value >> 8) & 0xff;
6686                         *p++ = (value >> 16) & 0xff;
6687                         *p++ = (value >> 24) & 0xff;
6688                 
6689                         checked_write_file (file, assembly->code.data, assembly->code.index);
6690                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6691                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6692                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6693                                 
6694
6695                         g_free (assembly->image.raw_metadata);
6696                         break;
6697                 case MONO_SECTION_RELOC: {
6698                         struct {
6699                                 guint32 page_rva;
6700                                 guint32 block_size;
6701                                 guint16 type_and_offset;
6702                                 guint16 term;
6703                         } reloc;
6704                         
6705                         g_assert (sizeof (reloc) == 12);
6706                         
6707                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6708                         reloc.block_size = GUINT32_FROM_LE (12);
6709                         
6710                         /* 
6711                          * the entrypoint is always at the start of the text section 
6712                          * 3 is IMAGE_REL_BASED_HIGHLOW
6713                          * 2 is patch_size_rva - text_rva
6714                          */
6715                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6716                         reloc.term = 0;
6717                         
6718                         checked_write_file (file, &reloc, sizeof (reloc));
6719                         
6720                         break;
6721                 }
6722                 case MONO_SECTION_RSRC:
6723                         if (assembly->win32_res) {
6724
6725                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6726                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6727                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6728                         }
6729                         break;
6730                 default:
6731                         g_assert_not_reached ();
6732                 }
6733         }
6734         
6735         /* check that the file is properly padded */
6736         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6737                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6738         if (! SetEndOfFile (file))
6739                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6740         
6741         mono_dynamic_stream_reset (&assembly->code);
6742         mono_dynamic_stream_reset (&assembly->us);
6743         mono_dynamic_stream_reset (&assembly->blob);
6744         mono_dynamic_stream_reset (&assembly->guid);
6745         mono_dynamic_stream_reset (&assembly->sheap);
6746
6747         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6748         g_hash_table_destroy (assembly->blob_cache);
6749         assembly->blob_cache = NULL;
6750
6751         return TRUE;
6752 }
6753
6754 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6755
6756 gboolean
6757 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6758 {
6759         g_assert_not_reached ();
6760 }
6761
6762 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6763
6764 #ifndef DISABLE_REFLECTION_EMIT
6765
6766 MonoReflectionModule *
6767 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6768 {
6769         char *name;
6770         MonoImage *image;
6771         MonoImageOpenStatus status;
6772         MonoDynamicAssembly *assembly;
6773         guint32 module_count;
6774         MonoImage **new_modules;
6775         gboolean *new_modules_loaded;
6776         
6777         mono_error_init (error);
6778         
6779         name = mono_string_to_utf8_checked (fileName, error);
6780         return_val_if_nok (error, NULL);
6781
6782         image = mono_image_open (name, &status);
6783         if (!image) {
6784                 if (status == MONO_IMAGE_ERROR_ERRNO)
6785                         mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6786                 else
6787                         mono_error_set_bad_image_name (error, name, NULL);
6788                 g_free (name);
6789                 return NULL;
6790         }
6791
6792         g_free (name);
6793
6794         assembly = ab->dynamic_assembly;
6795         image->assembly = (MonoAssembly*)assembly;
6796
6797         module_count = image->assembly->image->module_count;
6798         new_modules = g_new0 (MonoImage *, module_count + 1);
6799         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6800
6801         if (image->assembly->image->modules)
6802                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6803         if (image->assembly->image->modules_loaded)
6804                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6805         new_modules [module_count] = image;
6806         new_modules_loaded [module_count] = TRUE;
6807         mono_image_addref (image);
6808
6809         g_free (image->assembly->image->modules);
6810         image->assembly->image->modules = new_modules;
6811         image->assembly->image->modules_loaded = new_modules_loaded;
6812         image->assembly->image->module_count ++;
6813
6814         mono_assembly_load_references (image, &status);
6815         if (status) {
6816                 mono_image_close (image);
6817                 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6818                 return NULL;
6819         }
6820
6821         return mono_module_get_object_checked (mono_domain_get (), image, error);
6822 }
6823
6824 #endif /* DISABLE_REFLECTION_EMIT */
6825
6826 /*
6827  * We need to return always the same object for MethodInfo, FieldInfo etc..
6828  * but we need to consider the reflected type.
6829  * type uses a different hash, since it uses custom hash/equal functions.
6830  */
6831
6832 typedef struct {
6833         gpointer item;
6834         MonoClass *refclass;
6835 } ReflectedEntry;
6836
6837 static gboolean
6838 reflected_equal (gconstpointer a, gconstpointer b) {
6839         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6840         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6841
6842         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6843 }
6844
6845 static guint
6846 reflected_hash (gconstpointer a) {
6847         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6848         return mono_aligned_addr_hash (ea->item);
6849 }
6850
6851 #define CHECK_OBJECT(t,p,k)     \
6852         do {    \
6853                 t _obj; \
6854                 ReflectedEntry e;       \
6855                 e.item = (p);   \
6856                 e.refclass = (k);       \
6857                 mono_domain_lock (domain);      \
6858                 if (!domain->refobject_hash)    \
6859                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");  \
6860                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6861                         mono_domain_unlock (domain);    \
6862                         return _obj;    \
6863                 }       \
6864         mono_domain_unlock (domain); \
6865         } while (0)
6866
6867 #ifdef HAVE_BOEHM_GC
6868 /* ReflectedEntry doesn't need to be GC tracked */
6869 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6870 #define FREE_REFENTRY(entry) g_free ((entry))
6871 #define REFENTRY_REQUIRES_CLEANUP
6872 #else
6873 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6874 /* FIXME: */
6875 #define FREE_REFENTRY(entry)
6876 #endif
6877
6878 #define CACHE_OBJECT(t,p,o,k)   \
6879         do {    \
6880                 t _obj; \
6881         ReflectedEntry pe; \
6882         pe.item = (p); \
6883         pe.refclass = (k); \
6884         mono_domain_lock (domain); \
6885                 if (!domain->refobject_hash)    \
6886                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");  \
6887         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6888         if (!_obj) { \
6889                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6890                     e->item = (p);      \
6891                     e->refclass = (k);  \
6892                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6893             _obj = o; \
6894         } \
6895                 mono_domain_unlock (domain);    \
6896         return _obj; \
6897         } while (0)
6898
6899 static void
6900 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6901 {
6902         mono_domain_lock (domain);
6903         if (domain->refobject_hash) {
6904         ReflectedEntry pe;
6905                 gpointer orig_pe, orig_value;
6906
6907                 pe.item = o;
6908                 pe.refclass = klass;
6909                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6910                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6911                         FREE_REFENTRY (orig_pe);
6912                 }
6913         }
6914         mono_domain_unlock (domain);
6915 }
6916
6917 #ifdef REFENTRY_REQUIRES_CLEANUP
6918 static void
6919 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6920 {
6921         FREE_REFENTRY (key);
6922 }
6923 #endif
6924
6925 void
6926 mono_reflection_cleanup_domain (MonoDomain *domain)
6927 {
6928         if (domain->refobject_hash) {
6929 /*let's avoid scanning the whole hashtable if not needed*/
6930 #ifdef REFENTRY_REQUIRES_CLEANUP
6931                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6932 #endif
6933                 mono_g_hash_table_destroy (domain->refobject_hash);
6934                 domain->refobject_hash = NULL;
6935         }
6936 }
6937
6938 #ifndef DISABLE_REFLECTION_EMIT
6939 static gpointer
6940 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6941 {
6942         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6943 }
6944
6945 static gpointer
6946 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6947 {
6948         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6949 }
6950
6951 static gboolean
6952 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
6953 {
6954         MonoDynamicImage *image = moduleb->dynamic_image;
6955         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6956         mono_error_init (error);
6957         if (!image) {
6958                 int module_count;
6959                 MonoImage **new_modules;
6960                 MonoImage *ass;
6961                 char *name, *fqname;
6962                 /*
6963                  * FIXME: we already created an image in mono_image_basic_init (), but
6964                  * we don't know which module it belongs to, since that is only 
6965                  * determined at assembly save time.
6966                  */
6967                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6968                 name = mono_string_to_utf8_checked (ab->name, error);
6969                 return_val_if_nok (error, FALSE);
6970                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
6971                 if (!is_ok (error)) {
6972                         g_free (name);
6973                         return FALSE;
6974                 }
6975                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6976
6977                 moduleb->module.image = &image->image;
6978                 moduleb->dynamic_image = image;
6979                 register_module (mono_object_domain (moduleb), moduleb, image);
6980
6981                 /* register the module with the assembly */
6982                 ass = ab->dynamic_assembly->assembly.image;
6983                 module_count = ass->module_count;
6984                 new_modules = g_new0 (MonoImage *, module_count + 1);
6985
6986                 if (ass->modules)
6987                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6988                 new_modules [module_count] = &image->image;
6989                 mono_image_addref (&image->image);
6990
6991                 g_free (ass->modules);
6992                 ass->modules = new_modules;
6993                 ass->module_count ++;
6994         }
6995         return TRUE;
6996 }
6997
6998 void
6999 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
7000 {
7001         MonoError error;
7002         (void) image_module_basic_init (moduleb, &error);
7003         mono_error_set_pending_exception (&error);
7004 }
7005
7006 void
7007 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
7008 {
7009         MonoDynamicImage *image = moduleb->dynamic_image;
7010
7011         g_assert (type->type);
7012         image->wrappers_type = mono_class_from_mono_type (type->type);
7013 }
7014
7015 #endif
7016
7017 /*
7018  * mono_assembly_get_object:
7019  * @domain: an app domain
7020  * @assembly: an assembly
7021  *
7022  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
7023  */
7024 MonoReflectionAssembly*
7025 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
7026 {
7027         MonoError error;
7028         MonoReflectionAssembly *result;
7029         result = mono_assembly_get_object_checked (domain, assembly, &error);
7030         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7031         return result;
7032 }
7033 /*
7034  * mono_assembly_get_object_checked:
7035  * @domain: an app domain
7036  * @assembly: an assembly
7037  *
7038  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
7039  */
7040 MonoReflectionAssembly*
7041 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
7042 {
7043         MonoReflectionAssembly *res;
7044         
7045         mono_error_init (error);
7046
7047         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
7048         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
7049         if (!res)
7050                 return NULL;
7051         res->assembly = assembly;
7052
7053         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
7054 }
7055
7056
7057
7058 MonoReflectionModule*   
7059 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
7060 {
7061         MonoError error;
7062         MonoReflectionModule *result;
7063         result = mono_module_get_object_checked (domain, image, &error);
7064         mono_error_cleanup (&error);
7065         return result;
7066 }
7067
7068 MonoReflectionModule*
7069 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
7070 {
7071         MonoReflectionModule *res;
7072         char* basename;
7073         
7074         mono_error_init (error);
7075         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
7076         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7077         if (!res)
7078                 return NULL;
7079
7080         res->image = image;
7081         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7082         if (!assm_obj)
7083                 return NULL;
7084         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7085
7086         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
7087         basename = g_path_get_basename (image->name);
7088         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
7089         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
7090         
7091         g_free (basename);
7092
7093         if (image->assembly->image == image) {
7094                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
7095         } else {
7096                 int i;
7097                 res->token = 0;
7098                 if (image->assembly->image->modules) {
7099                         for (i = 0; i < image->assembly->image->module_count; i++) {
7100                                 if (image->assembly->image->modules [i] == image)
7101                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
7102                         }
7103                         g_assert (res->token);
7104                 }
7105         }
7106
7107         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7108 }
7109
7110 MonoReflectionModule*
7111 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7112 {
7113         MonoError error;
7114         MonoReflectionModule *result;
7115         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7116         mono_error_cleanup (&error);
7117         return result;
7118 }
7119
7120 MonoReflectionModule*
7121 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7122 {
7123         MonoReflectionModule *res;
7124         MonoTableInfo *table;
7125         guint32 cols [MONO_FILE_SIZE];
7126         const char *name;
7127         guint32 i, name_idx;
7128         const char *val;
7129         
7130         mono_error_init (error);
7131
7132         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7133         if (!res)
7134                 return NULL;
7135
7136         table = &image->tables [MONO_TABLE_FILE];
7137         g_assert (table_index < table->rows);
7138         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7139
7140         res->image = NULL;
7141         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7142         if (!assm_obj)
7143                 return NULL;
7144         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7145         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7146
7147         /* Check whenever the row has a corresponding row in the moduleref table */
7148         table = &image->tables [MONO_TABLE_MODULEREF];
7149         for (i = 0; i < table->rows; ++i) {
7150                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7151                 val = mono_metadata_string_heap (image, name_idx);
7152                 if (strcmp (val, name) == 0)
7153                         res->image = image->modules [i];
7154         }
7155
7156         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7157         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7158         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7159         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7160         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7161
7162         return res;
7163 }
7164
7165 static gboolean
7166 verify_safe_for_managed_space (MonoType *type)
7167 {
7168         switch (type->type) {
7169 #ifdef DEBUG_HARDER
7170         case MONO_TYPE_ARRAY:
7171                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7172         case MONO_TYPE_PTR:
7173                 return verify_safe_for_managed_space (type->data.type);
7174         case MONO_TYPE_SZARRAY:
7175                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7176         case MONO_TYPE_GENERICINST: {
7177                 MonoGenericInst *inst = type->data.generic_class->inst;
7178                 int i;
7179                 if (!inst->is_open)
7180                         break;
7181                 for (i = 0; i < inst->type_argc; ++i)
7182                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7183                                 return FALSE;
7184                 return TRUE;
7185         }
7186 #endif
7187         case MONO_TYPE_VAR:
7188         case MONO_TYPE_MVAR:
7189                 return TRUE;
7190         default:
7191                 return TRUE;
7192         }
7193 }
7194
7195 static MonoType*
7196 mono_type_normalize (MonoType *type)
7197 {
7198         int i;
7199         MonoGenericClass *gclass;
7200         MonoGenericInst *ginst;
7201         MonoClass *gtd;
7202         MonoGenericContainer *gcontainer;
7203         MonoType **argv = NULL;
7204         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7205
7206         if (type->type != MONO_TYPE_GENERICINST)
7207                 return type;
7208
7209         gclass = type->data.generic_class;
7210         ginst = gclass->context.class_inst;
7211         if (!ginst->is_open)
7212                 return type;
7213
7214         gtd = gclass->container_class;
7215         gcontainer = gtd->generic_container;
7216         argv = g_newa (MonoType*, ginst->type_argc);
7217
7218         for (i = 0; i < ginst->type_argc; ++i) {
7219                 MonoType *t = ginst->type_argv [i], *norm;
7220                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7221                         is_denorm_gtd = FALSE;
7222                 norm = mono_type_normalize (t);
7223                 argv [i] = norm;
7224                 if (norm != t)
7225                         requires_rebind = TRUE;
7226         }
7227
7228         if (is_denorm_gtd)
7229                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7230
7231         if (requires_rebind) {
7232                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7233                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7234         }
7235
7236         return type;
7237 }
7238 /*
7239  * mono_type_get_object:
7240  * @domain: an app domain
7241  * @type: a type
7242  *
7243  * Return an System.MonoType object representing the type @type.
7244  */
7245 MonoReflectionType*
7246 mono_type_get_object (MonoDomain *domain, MonoType *type)
7247 {
7248         MonoError error;
7249         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7250         mono_error_cleanup (&error);
7251
7252         return ret;
7253 }
7254
7255 MonoReflectionType*
7256 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7257 {
7258         MonoType *norm_type;
7259         MonoReflectionType *res;
7260         MonoClass *klass;
7261
7262         mono_error_init (error);
7263
7264         klass = mono_class_from_mono_type (type);
7265
7266         /*we must avoid using @type as it might have come
7267          * from a mono_metadata_type_dup and the caller
7268          * expects that is can be freed.
7269          * Using the right type from 
7270          */
7271         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7272
7273         /* void is very common */
7274         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7275                 return (MonoReflectionType*)domain->typeof_void;
7276
7277         /*
7278          * If the vtable of the given class was already created, we can use
7279          * the MonoType from there and avoid all locking and hash table lookups.
7280          * 
7281          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7282          * that the resulting object is different.   
7283          */
7284         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7285                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7286                 if (vtable && vtable->type)
7287                         return (MonoReflectionType *)vtable->type;
7288         }
7289
7290         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7291         mono_domain_lock (domain);
7292         if (!domain->type_hash)
7293                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7294                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7295         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7296                 mono_domain_unlock (domain);
7297                 mono_loader_unlock ();
7298                 return res;
7299         }
7300
7301         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7302          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7303          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7304          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7305          * artifact of how generics are encoded and should be transparent to managed code so we
7306          * need to weed out this diference when retrieving managed System.Type objects.
7307          */
7308         norm_type = mono_type_normalize (type);
7309         if (norm_type != type) {
7310                 res = mono_type_get_object_checked (domain, norm_type, error);
7311                 if (!mono_error_ok (error))
7312                         return NULL;
7313                 mono_g_hash_table_insert (domain->type_hash, type, res);
7314                 mono_domain_unlock (domain);
7315                 mono_loader_unlock ();
7316                 return res;
7317         }
7318
7319         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7320         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7321                 g_assert (0);
7322
7323         if (!verify_safe_for_managed_space (type)) {
7324                 mono_domain_unlock (domain);
7325                 mono_loader_unlock ();
7326                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7327                 return NULL;
7328         }
7329
7330         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7331                 gboolean is_type_done = TRUE;
7332                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7333                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7334                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7335                 */
7336                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7337                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7338
7339                         if (gparam->owner && gparam->owner->is_method) {
7340                                 MonoMethod *method = gparam->owner->owner.method;
7341                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7342                                         is_type_done = FALSE;
7343                         } else if (gparam->owner && !gparam->owner->is_method) {
7344                                 MonoClass *klass = gparam->owner->owner.klass;
7345                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7346                                         is_type_done = FALSE;
7347                         }
7348                 } 
7349
7350                 /* g_assert_not_reached (); */
7351                 /* should this be considered an error condition? */
7352                 if (is_type_done && !type->byref) {
7353                         mono_domain_unlock (domain);
7354                         mono_loader_unlock ();
7355                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7356                 }
7357         }
7358         /* This is stored in vtables/JITted code so it has to be pinned */
7359         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error);
7360         if (!mono_error_ok (error))
7361                 return NULL;
7362
7363         res->type = type;
7364         mono_g_hash_table_insert (domain->type_hash, type, res);
7365
7366         if (type->type == MONO_TYPE_VOID)
7367                 domain->typeof_void = (MonoObject*)res;
7368
7369         mono_domain_unlock (domain);
7370         mono_loader_unlock ();
7371         return res;
7372 }
7373
7374 /*
7375  * mono_method_get_object:
7376  * @domain: an app domain
7377  * @method: a method
7378  * @refclass: the reflected type (can be NULL)
7379  *
7380  * Return an System.Reflection.MonoMethod object representing the method @method.
7381  */
7382 MonoReflectionMethod*
7383 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7384 {
7385         MonoError error;
7386         MonoReflectionMethod *ret = NULL;
7387         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7388         mono_error_cleanup (&error);
7389         return ret;
7390 }
7391
7392 /*
7393  * mono_method_get_object_checked:
7394  * @domain: an app domain
7395  * @method: a method
7396  * @refclass: the reflected type (can be NULL)
7397  * @error: set on error.
7398  *
7399  * Return an System.Reflection.MonoMethod object representing the method @method.
7400  * Returns NULL and sets @error on error.
7401  */
7402 MonoReflectionMethod*
7403 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7404 {
7405         /*
7406          * We use the same C representation for methods and constructors, but the type 
7407          * name in C# is different.
7408          */
7409         MonoReflectionType *rt;
7410         MonoClass *klass;
7411         MonoReflectionMethod *ret;
7412
7413         mono_error_init (error);
7414
7415         if (method->is_inflated) {
7416                 MonoReflectionGenericMethod *gret;
7417
7418                 if (!refclass)
7419                         refclass = method->klass;
7420                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7421                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7422                         klass = mono_class_get_mono_generic_cmethod_class ();
7423                 } else {
7424                         klass = mono_class_get_mono_generic_method_class ();
7425                 }
7426                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7427                 if (!mono_error_ok (error))
7428                         goto leave;
7429                 gret->method.method = method;
7430
7431                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7432
7433                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7434                 if (!mono_error_ok (error))
7435                     goto leave;
7436
7437                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7438
7439                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7440         }
7441
7442         if (!refclass)
7443                 refclass = method->klass;
7444
7445         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7446         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7447                 klass = mono_class_get_mono_cmethod_class ();
7448         }
7449         else {
7450                 klass = mono_class_get_mono_method_class ();
7451         }
7452         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7453         if (!mono_error_ok (error))
7454                 goto leave;
7455         ret->method = method;
7456
7457         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7458         if (!mono_error_ok (error))
7459                 goto leave;
7460
7461         MONO_OBJECT_SETREF (ret, reftype, rt);
7462
7463         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7464
7465 leave:
7466         g_assert (!mono_error_ok (error));
7467         return NULL;
7468 }
7469
7470 /*
7471  * mono_method_clear_object:
7472  *
7473  *   Clear the cached reflection objects for the dynamic method METHOD.
7474  */
7475 void
7476 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7477 {
7478         MonoClass *klass;
7479         g_assert (method_is_dynamic (method));
7480
7481         klass = method->klass;
7482         while (klass) {
7483                 clear_cached_object (domain, method, klass);
7484                 klass = klass->parent;
7485         }
7486         /* Added by mono_param_get_objects () */
7487         clear_cached_object (domain, &(method->signature), NULL);
7488         klass = method->klass;
7489         while (klass) {
7490                 clear_cached_object (domain, &(method->signature), klass);
7491                 klass = klass->parent;
7492         }
7493 }
7494
7495 /*
7496  * mono_field_get_object:
7497  * @domain: an app domain
7498  * @klass: a type
7499  * @field: a field
7500  *
7501  * Return an System.Reflection.MonoField object representing the field @field
7502  * in class @klass.
7503  */
7504 MonoReflectionField*
7505 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7506 {
7507         MonoError error;
7508         MonoReflectionField *result;
7509         result = mono_field_get_object_checked (domain, klass, field, &error);
7510         mono_error_cleanup (&error);
7511         return result;
7512 }
7513
7514 /*
7515  * mono_field_get_object_checked:
7516  * @domain: an app domain
7517  * @klass: a type
7518  * @field: a field
7519  * @error: set on error
7520  *
7521  * Return an System.Reflection.MonoField object representing the field @field
7522  * in class @klass. On error, returns NULL and sets @error.
7523  */
7524 MonoReflectionField*
7525 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7526 {
7527         MonoReflectionType *rt;
7528         MonoReflectionField *res;
7529
7530         mono_error_init (error);
7531
7532         CHECK_OBJECT (MonoReflectionField *, field, klass);
7533         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7534         if (!res)
7535                 return NULL;
7536         res->klass = klass;
7537         res->field = field;
7538         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7539
7540         if (is_field_on_inst (field)) {
7541                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7542
7543                 rt = mono_type_get_object_checked (domain, field->type, error);
7544                 if (!mono_error_ok (error))
7545                         return NULL;
7546
7547                 MONO_OBJECT_SETREF (res, type, rt);
7548         } else {
7549                 if (field->type) {
7550                         rt = mono_type_get_object_checked (domain, field->type, error);
7551                         if (!mono_error_ok (error))
7552                                 return NULL;
7553
7554                         MONO_OBJECT_SETREF (res, type, rt);
7555                 }
7556                 res->attrs = mono_field_get_flags (field);
7557         }
7558         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7559 }
7560
7561 /*
7562  * mono_property_get_object:
7563  * @domain: an app domain
7564  * @klass: a type
7565  * @property: a property
7566  *
7567  * Return an System.Reflection.MonoProperty object representing the property @property
7568  * in class @klass.
7569  */
7570 MonoReflectionProperty*
7571 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7572 {
7573         MonoError error;
7574         MonoReflectionProperty *result;
7575         result = mono_property_get_object_checked (domain, klass, property, &error);
7576         mono_error_cleanup (&error);
7577         return result;
7578 }
7579
7580 /**
7581  * mono_property_get_object:
7582  * @domain: an app domain
7583  * @klass: a type
7584  * @property: a property
7585  * @error: set on error
7586  *
7587  * Return an System.Reflection.MonoProperty object representing the property @property
7588  * in class @klass.  On error returns NULL and sets @error.
7589  */
7590 MonoReflectionProperty*
7591 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7592 {
7593         MonoReflectionProperty *res;
7594
7595         mono_error_init (error);
7596
7597         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7598         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7599         if (!res)
7600                 return NULL;
7601         res->klass = klass;
7602         res->property = property;
7603         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7604 }
7605
7606 /*
7607  * mono_event_get_object:
7608  * @domain: an app domain
7609  * @klass: a type
7610  * @event: a event
7611  *
7612  * Return an System.Reflection.MonoEvent object representing the event @event
7613  * in class @klass.
7614  */
7615 MonoReflectionEvent*
7616 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7617 {
7618         MonoError error;
7619         MonoReflectionEvent *result;
7620         result = mono_event_get_object_checked (domain, klass, event, &error);
7621         mono_error_cleanup (&error);
7622         return result;
7623 }
7624
7625 /**
7626  * mono_event_get_object_checked:
7627  * @domain: an app domain
7628  * @klass: a type
7629  * @event: a event
7630  * @error: set on error
7631  *
7632  * Return an System.Reflection.MonoEvent object representing the event @event
7633  * in class @klass. On failure sets @error and returns NULL
7634  */
7635 MonoReflectionEvent*
7636 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7637 {
7638         MonoReflectionEvent *res;
7639         MonoReflectionMonoEvent *mono_event;
7640
7641         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7642         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7643         if (!mono_event)
7644                 return NULL;
7645         mono_event->klass = klass;
7646         mono_event->event = event;
7647         res = (MonoReflectionEvent*)mono_event;
7648         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7649 }
7650
7651 /**
7652  * mono_get_reflection_missing_object:
7653  * @domain: Domain where the object lives
7654  *
7655  * Returns the System.Reflection.Missing.Value singleton object
7656  * (of type System.Reflection.Missing).
7657  *
7658  * Used as the value for ParameterInfo.DefaultValue when Optional
7659  * is present
7660  */
7661 static MonoObject *
7662 mono_get_reflection_missing_object (MonoDomain *domain)
7663 {
7664         MonoError error;
7665         MonoObject *obj;
7666         static MonoClassField *missing_value_field = NULL;
7667         
7668         if (!missing_value_field) {
7669                 MonoClass *missing_klass;
7670                 missing_klass = mono_class_get_missing_class ();
7671                 mono_class_init (missing_klass);
7672                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7673                 g_assert (missing_value_field);
7674         }
7675         obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7676         mono_error_assert_ok (&error);
7677         return obj;
7678 }
7679
7680 static MonoObject*
7681 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7682 {
7683         if (!*dbnull)
7684                 *dbnull = mono_get_dbnull_object (domain);
7685         return *dbnull;
7686 }
7687
7688 static MonoObject*
7689 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7690 {
7691         if (!*reflection_missing)
7692                 *reflection_missing = mono_get_reflection_missing_object (domain);
7693         return *reflection_missing;
7694 }
7695
7696 /*
7697  * mono_param_get_objects:
7698  * @domain: an app domain
7699  * @method: a method
7700  *
7701  * Return an System.Reflection.ParameterInfo array object representing the parameters
7702  * in the method @method.
7703  */
7704 MonoArray*
7705 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7706 {
7707         static MonoClass *System_Reflection_ParameterInfo;
7708         static MonoClass *System_Reflection_ParameterInfo_array;
7709         MonoArray *res = NULL;
7710         MonoReflectionMethod *member = NULL;
7711         MonoReflectionParameter *param = NULL;
7712         char **names = NULL, **blobs = NULL;
7713         guint32 *types = NULL;
7714         MonoType *type = NULL;
7715         MonoObject *dbnull = NULL;
7716         MonoObject *missing = NULL;
7717         MonoMarshalSpec **mspecs = NULL;
7718         MonoMethodSignature *sig = NULL;
7719         MonoVTable *pinfo_vtable;
7720         MonoReflectionType *rt;
7721         int i;
7722
7723         mono_error_init (error);
7724         
7725         if (!System_Reflection_ParameterInfo_array) {
7726                 MonoClass *klass;
7727
7728                 klass = mono_class_get_mono_parameter_info_class ();
7729
7730                 mono_memory_barrier ();
7731                 System_Reflection_ParameterInfo = klass; 
7732
7733         
7734                 klass = mono_array_class_get (klass, 1);
7735                 mono_memory_barrier ();
7736                 System_Reflection_ParameterInfo_array = klass;
7737         }
7738
7739         sig = mono_method_signature_checked (method, error);
7740         if (!mono_error_ok (error))
7741                 goto leave;
7742
7743         if (!sig->param_count) {
7744                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7745                 if (!res)
7746                         goto leave;
7747
7748                 return res;
7749         }
7750
7751         /* Note: the cache is based on the address of the signature into the method
7752          * since we already cache MethodInfos with the method as keys.
7753          */
7754         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7755
7756         member = mono_method_get_object_checked (domain, method, refclass, error);
7757         if (!member)
7758                 goto leave;
7759         names = g_new (char *, sig->param_count);
7760         mono_method_get_param_names (method, (const char **) names);
7761
7762         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7763         mono_method_get_marshal_info (method, mspecs);
7764
7765         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7766         if (!res)
7767                 goto leave;
7768
7769         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7770         for (i = 0; i < sig->param_count; ++i) {
7771                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7772                 if (!param)
7773                         goto leave;
7774
7775                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7776                 if (!rt)
7777                         goto leave;
7778
7779                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7780
7781                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7782
7783                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7784
7785                 param->PositionImpl = i;
7786                 param->AttrsImpl = sig->params [i]->attrs;
7787
7788                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7789                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7790                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7791                         else
7792                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7793                 } else {
7794
7795                         if (!blobs) {
7796                                 blobs = g_new0 (char *, sig->param_count);
7797                                 types = g_new0 (guint32, sig->param_count);
7798                                 get_default_param_value_blobs (method, blobs, types); 
7799                         }
7800
7801                         /* Build MonoType for the type from the Constant Table */
7802                         if (!type)
7803                                 type = g_new0 (MonoType, 1);
7804                         type->type = (MonoTypeEnum)types [i];
7805                         type->data.klass = NULL;
7806                         if (types [i] == MONO_TYPE_CLASS)
7807                                 type->data.klass = mono_defaults.object_class;
7808                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7809                                 /* For enums, types [i] contains the base type */
7810
7811                                         type->type = MONO_TYPE_VALUETYPE;
7812                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7813                         } else
7814                                 type->data.klass = mono_class_from_mono_type (type);
7815
7816                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7817                         if (!is_ok (error))
7818                                 goto leave;
7819                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7820
7821                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7822                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7823                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7824                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7825                                 else
7826                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7827                         }
7828                         
7829                 }
7830
7831                 if (mspecs [i + 1]) {
7832                         MonoReflectionMarshalAsAttribute* mobj;
7833                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7834                         if (!mobj)
7835                                 goto leave;
7836                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7837                 }
7838                 
7839                 mono_array_setref (res, i, param);
7840         }
7841
7842 leave:
7843         g_free (names);
7844         g_free (blobs);
7845         g_free (types);
7846         g_free (type);
7847
7848         if (sig) {
7849                 for (i = sig->param_count; i >= 0; i--) {
7850                         if (mspecs [i])
7851                                 mono_metadata_free_marshal_spec (mspecs [i]);
7852                 }
7853         }
7854         g_free (mspecs);
7855
7856         if (!is_ok (error))
7857                 return NULL;
7858         
7859         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7860 }
7861
7862 MonoArray*
7863 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7864 {
7865         MonoError error;
7866         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7867         mono_error_assert_ok (&error);
7868         return result;
7869 }
7870
7871 /*
7872  * mono_method_body_get_object:
7873  * @domain: an app domain
7874  * @method: a method
7875  *
7876  * Return an System.Reflection.MethodBody object representing the method @method.
7877  */
7878 MonoReflectionMethodBody*
7879 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7880 {
7881         MonoError error;
7882         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7883         mono_error_cleanup (&error);
7884         return result;
7885 }
7886
7887 /**
7888  * mono_method_body_get_object_checked:
7889  * @domain: an app domain
7890  * @method: a method
7891  * @error: set on error
7892  *
7893  * Return an System.Reflection.MethodBody object representing the
7894  * method @method.  On failure, returns NULL and sets @error.
7895  */
7896 MonoReflectionMethodBody*
7897 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7898 {
7899         MonoReflectionMethodBody *ret;
7900         MonoMethodHeader *header;
7901         MonoImage *image;
7902         MonoReflectionType *rt;
7903         guint32 method_rva, local_var_sig_token;
7904         char *ptr;
7905         unsigned char format, flags;
7906         int i;
7907
7908         mono_error_init (error);
7909
7910         /* for compatibility with .net */
7911         if (method_is_dynamic (method)) {
7912                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7913                 return NULL;
7914         }
7915
7916         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7917
7918         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7919                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7920             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7921                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7922             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7923                 return NULL;
7924
7925         image = method->klass->image;
7926         header = mono_method_get_header_checked (method, error);
7927         return_val_if_nok (error, NULL);
7928
7929         if (!image_is_dynamic (image)) {
7930                 /* Obtain local vars signature token */
7931                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7932                 ptr = mono_image_rva_map (image, method_rva);
7933                 flags = *(const unsigned char *) ptr;
7934                 format = flags & METHOD_HEADER_FORMAT_MASK;
7935                 switch (format){
7936                 case METHOD_HEADER_TINY_FORMAT:
7937                         local_var_sig_token = 0;
7938                         break;
7939                 case METHOD_HEADER_FAT_FORMAT:
7940                         ptr += 2;
7941                         ptr += 2;
7942                         ptr += 4;
7943                         local_var_sig_token = read32 (ptr);
7944                         break;
7945                 default:
7946                         g_assert_not_reached ();
7947                 }
7948         } else
7949                 local_var_sig_token = 0; //FIXME
7950
7951         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7952         if (!is_ok (error))
7953                 goto fail;
7954
7955         ret->init_locals = header->init_locals;
7956         ret->max_stack = header->max_stack;
7957         ret->local_var_sig_token = local_var_sig_token;
7958         MonoArray *il_arr = mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size, error);
7959         if (!is_ok (error))
7960                 goto fail;
7961         MONO_OBJECT_SETREF (ret, il, il_arr);
7962         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7963
7964         /* Locals */
7965         MonoArray *locals_arr = mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals, error);
7966         if (!is_ok (error))
7967                 goto fail;
7968         MONO_OBJECT_SETREF (ret, locals, locals_arr);
7969         for (i = 0; i < header->num_locals; ++i) {
7970                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7971                 if (!is_ok (error))
7972                         goto fail;
7973
7974                 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7975                 if (!is_ok (error))
7976                         goto fail;
7977
7978                 MONO_OBJECT_SETREF (info, local_type, rt);
7979
7980                 info->is_pinned = header->locals [i]->pinned;
7981                 info->local_index = i;
7982                 mono_array_setref (ret->locals, i, info);
7983         }
7984
7985         /* Exceptions */
7986         MonoArray *exn_clauses = mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses, error);
7987         if (!is_ok (error))
7988                 goto fail;
7989         MONO_OBJECT_SETREF (ret, clauses, exn_clauses);
7990         for (i = 0; i < header->num_clauses; ++i) {
7991                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7992                 if (!is_ok (error))
7993                         goto fail;
7994                 MonoExceptionClause *clause = &header->clauses [i];
7995
7996                 info->flags = clause->flags;
7997                 info->try_offset = clause->try_offset;
7998                 info->try_length = clause->try_len;
7999                 info->handler_offset = clause->handler_offset;
8000                 info->handler_length = clause->handler_len;
8001                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
8002                         info->filter_offset = clause->data.filter_offset;
8003                 else if (clause->data.catch_class) {
8004                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
8005                         if (!is_ok (error))
8006                                 goto fail;
8007
8008                         MONO_OBJECT_SETREF (info, catch_type, rt);
8009                 }
8010
8011                 mono_array_setref (ret->clauses, i, info);
8012         }
8013
8014         mono_metadata_free_mh (header);
8015         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
8016         return ret;
8017
8018 fail:
8019         mono_metadata_free_mh (header);
8020         return NULL;
8021 }
8022
8023 /**
8024  * mono_get_dbnull_object:
8025  * @domain: Domain where the object lives
8026  *
8027  * Returns the System.DBNull.Value singleton object
8028  *
8029  * Used as the value for ParameterInfo.DefaultValue 
8030  */
8031 MonoObject *
8032 mono_get_dbnull_object (MonoDomain *domain)
8033 {
8034         MonoError error;
8035         MonoObject *obj;
8036         static MonoClassField *dbnull_value_field = NULL;
8037         
8038         if (!dbnull_value_field) {
8039                 MonoClass *dbnull_klass;
8040                 dbnull_klass = mono_class_get_dbnull_class ();
8041                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
8042                 g_assert (dbnull_value_field);
8043         }
8044         obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
8045         mono_error_assert_ok (&error);
8046         return obj;
8047 }
8048
8049 static void
8050 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
8051 {
8052         guint32 param_index, i, lastp, crow = 0;
8053         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
8054         gint32 idx;
8055
8056         MonoClass *klass = method->klass;
8057         MonoImage *image = klass->image;
8058         MonoMethodSignature *methodsig = mono_method_signature (method);
8059
8060         MonoTableInfo *constt;
8061         MonoTableInfo *methodt;
8062         MonoTableInfo *paramt;
8063
8064         if (!methodsig->param_count)
8065                 return;
8066
8067         mono_class_init (klass);
8068
8069         if (image_is_dynamic (klass->image)) {
8070                 MonoReflectionMethodAux *aux;
8071                 if (method->is_inflated)
8072                         method = ((MonoMethodInflated*)method)->declaring;
8073                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8074                 if (aux && aux->param_defaults) {
8075                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
8076                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
8077                 }
8078                 return;
8079         }
8080
8081         methodt = &klass->image->tables [MONO_TABLE_METHOD];
8082         paramt = &klass->image->tables [MONO_TABLE_PARAM];
8083         constt = &image->tables [MONO_TABLE_CONSTANT];
8084
8085         idx = mono_method_get_index (method) - 1;
8086         g_assert (idx != -1);
8087
8088         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
8089         if (idx + 1 < methodt->rows)
8090                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
8091         else
8092                 lastp = paramt->rows + 1;
8093
8094         for (i = param_index; i < lastp; ++i) {
8095                 guint32 paramseq;
8096
8097                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
8098                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
8099
8100                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
8101                         continue;
8102
8103                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
8104                 if (!crow) {
8105                         continue;
8106                 }
8107         
8108                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
8109                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
8110                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8111         }
8112
8113         return;
8114 }
8115
8116 MonoObject *
8117 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8118 {
8119         void *retval;
8120         MonoClass *klass;
8121         MonoObject *object;
8122         MonoType *basetype = type;
8123
8124         mono_error_init (error);
8125
8126         if (!blob)
8127                 return NULL;
8128         
8129         klass = mono_class_from_mono_type (type);
8130         if (klass->valuetype) {
8131                 object = mono_object_new_checked (domain, klass, error);
8132                 return_val_if_nok (error, NULL);
8133                 retval = ((gchar *) object + sizeof (MonoObject));
8134                 if (klass->enumtype)
8135                         basetype = mono_class_enum_basetype (klass);
8136         } else {
8137                 retval = &object;
8138         }
8139                         
8140         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval, error))
8141                 return object;
8142         else
8143                 return NULL;
8144 }
8145
8146 static int
8147 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8148         int found_sep;
8149         char *s;
8150         gboolean quoted = FALSE;
8151
8152         memset (assembly, 0, sizeof (MonoAssemblyName));
8153         assembly->culture = "";
8154         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8155
8156         if (*p == '"') {
8157                 quoted = TRUE;
8158                 p++;
8159         }
8160         assembly->name = p;
8161         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8162                 p++;
8163         if (quoted) {
8164                 if (*p != '"')
8165                         return 1;
8166                 *p = 0;
8167                 p++;
8168         }
8169         if (*p != ',')
8170                 return 1;
8171         *p = 0;
8172         /* Remove trailing whitespace */
8173         s = p - 1;
8174         while (*s && g_ascii_isspace (*s))
8175                 *s-- = 0;
8176         p ++;
8177         while (g_ascii_isspace (*p))
8178                 p++;
8179         while (*p) {
8180                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8181                         p += 8;
8182                         assembly->major = strtoul (p, &s, 10);
8183                         if (s == p || *s != '.')
8184                                 return 1;
8185                         p = ++s;
8186                         assembly->minor = strtoul (p, &s, 10);
8187                         if (s == p || *s != '.')
8188                                 return 1;
8189                         p = ++s;
8190                         assembly->build = strtoul (p, &s, 10);
8191                         if (s == p || *s != '.')
8192                                 return 1;
8193                         p = ++s;
8194                         assembly->revision = strtoul (p, &s, 10);
8195                         if (s == p)
8196                                 return 1;
8197                         p = s;
8198                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8199                         p += 8;
8200                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8201                                 assembly->culture = "";
8202                                 p += 7;
8203                         } else {
8204                                 assembly->culture = p;
8205                                 while (*p && *p != ',') {
8206                                         p++;
8207                                 }
8208                         }
8209                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8210                         p += 15;
8211                         if (strncmp (p, "null", 4) == 0) {
8212                                 p += 4;
8213                         } else {
8214                                 int len;
8215                                 gchar *start = p;
8216                                 while (*p && *p != ',') {
8217                                         p++;
8218                                 }
8219                                 len = (p - start + 1);
8220                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8221                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8222                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8223                         }
8224                 } else {
8225                         while (*p && *p != ',')
8226                                 p++;
8227                 }
8228                 found_sep = 0;
8229                 while (g_ascii_isspace (*p) || *p == ',') {
8230                         *p++ = 0;
8231                         found_sep = 1;
8232                         continue;
8233                 }
8234                 /* failed */
8235                 if (!found_sep)
8236                         return 1;
8237         }
8238
8239         return 0;
8240 }
8241
8242 /*
8243  * mono_reflection_parse_type:
8244  * @name: type name
8245  *
8246  * Parse a type name as accepted by the GetType () method and output the info
8247  * extracted in the info structure.
8248  * the name param will be mangled, so, make a copy before passing it to this function.
8249  * The fields in info will be valid until the memory pointed to by name is valid.
8250  *
8251  * See also mono_type_get_name () below.
8252  *
8253  * Returns: 0 on parse error.
8254  */
8255 static int
8256 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8257                              MonoTypeNameParse *info)
8258 {
8259         char *start, *p, *w, *last_point, *startn;
8260         int in_modifiers = 0;
8261         int isbyref = 0, rank = 0, isptr = 0;
8262
8263         start = p = w = name;
8264
8265         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8266         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8267         info->name = info->name_space = NULL;
8268         info->nested = NULL;
8269         info->modifiers = NULL;
8270         info->type_arguments = NULL;
8271
8272         /* last_point separates the namespace from the name */
8273         last_point = NULL;
8274         /* Skips spaces */
8275         while (*p == ' ') p++, start++, w++, name++;
8276
8277         while (*p) {
8278                 switch (*p) {
8279                 case '+':
8280                         *p = 0; /* NULL terminate the name */
8281                         startn = p + 1;
8282                         info->nested = g_list_append (info->nested, startn);
8283                         /* we have parsed the nesting namespace + name */
8284                         if (info->name)
8285                                 break;
8286                         if (last_point) {
8287                                 info->name_space = start;
8288                                 *last_point = 0;
8289                                 info->name = last_point + 1;
8290                         } else {
8291                                 info->name_space = (char *)"";
8292                                 info->name = start;
8293                         }
8294                         break;
8295                 case '.':
8296                         last_point = p;
8297                         break;
8298                 case '\\':
8299                         ++p;
8300                         break;
8301                 case '&':
8302                 case '*':
8303                 case '[':
8304                 case ',':
8305                 case ']':
8306                         in_modifiers = 1;
8307                         break;
8308                 default:
8309                         break;
8310                 }
8311                 if (in_modifiers)
8312                         break;
8313                 // *w++ = *p++;
8314                 p++;
8315         }
8316         
8317         if (!info->name) {
8318                 if (last_point) {
8319                         info->name_space = start;
8320                         *last_point = 0;
8321                         info->name = last_point + 1;
8322                 } else {
8323                         info->name_space = (char *)"";
8324                         info->name = start;
8325                 }
8326         }
8327         while (*p) {
8328                 switch (*p) {
8329                 case '&':
8330                         if (isbyref) /* only one level allowed by the spec */
8331                                 return 0;
8332                         isbyref = 1;
8333                         isptr = 0;
8334                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8335                         *p++ = 0;
8336                         break;
8337                 case '*':
8338                         if (isbyref) /* pointer to ref not okay */
8339                                 return 0;
8340                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8341                         isptr = 1;
8342                         *p++ = 0;
8343                         break;
8344                 case '[':
8345                         if (isbyref) /* array of ref and generic ref are not okay */
8346                                 return 0;
8347                         //Decide if it's an array of a generic argument list
8348                         *p++ = 0;
8349
8350                         if (!*p) //XXX test
8351                                 return 0;
8352                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8353                                 isptr = 0;
8354                                 rank = 1;
8355                                 while (*p) {
8356                                         if (*p == ']')
8357                                                 break;
8358                                         if (*p == ',')
8359                                                 rank++;
8360                                         else if (*p == '*') /* '*' means unknown lower bound */
8361                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8362                                         else
8363                                                 return 0;
8364                                         ++p;
8365                                 }
8366                                 if (*p++ != ']')
8367                                         return 0;
8368                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8369                         } else {
8370                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8371                                         return 0;
8372                                 isptr = 0;
8373                                 info->type_arguments = g_ptr_array_new ();
8374                                 while (*p) {
8375                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8376                                         gboolean fqname = FALSE;
8377
8378                                         g_ptr_array_add (info->type_arguments, subinfo);
8379
8380                                         while (*p == ' ') p++;
8381                                         if (*p == '[') {
8382                                                 p++;
8383                                                 fqname = TRUE;
8384                                         }
8385
8386                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8387                                                 return 0;
8388
8389                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8390                                         if (fqname && (*p != ']')) {
8391                                                 char *aname;
8392
8393                                                 if (*p != ',')
8394                                                         return 0;
8395                                                 *p++ = 0;
8396
8397                                                 aname = p;
8398                                                 while (*p && (*p != ']'))
8399                                                         p++;
8400
8401                                                 if (*p != ']')
8402                                                         return 0;
8403
8404                                                 *p++ = 0;
8405                                                 while (*aname) {
8406                                                         if (g_ascii_isspace (*aname)) {
8407                                                                 ++aname;
8408                                                                 continue;
8409                                                         }
8410                                                         break;
8411                                                 }
8412                                                 if (!*aname ||
8413                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8414                                                         return 0;
8415                                         } else if (fqname && (*p == ']')) {
8416                                                 *p++ = 0;
8417                                         }
8418                                         if (*p == ']') {
8419                                                 *p++ = 0;
8420                                                 break;
8421                                         } else if (!*p) {
8422                                                 return 0;
8423                                         }
8424                                         *p++ = 0;
8425                                 }
8426                         }
8427                         break;
8428                 case ']':
8429                         if (is_recursed)
8430                                 goto end;
8431                         return 0;
8432                 case ',':
8433                         if (is_recursed)
8434                                 goto end;
8435                         *p++ = 0;
8436                         while (*p) {
8437                                 if (g_ascii_isspace (*p)) {
8438                                         ++p;
8439                                         continue;
8440                                 }
8441                                 break;
8442                         }
8443                         if (!*p)
8444                                 return 0; /* missing assembly name */
8445                         if (!assembly_name_to_aname (&info->assembly, p))
8446                                 return 0;
8447                         break;
8448                 default:
8449                         return 0;
8450                 }
8451                 if (info->assembly.name)
8452                         break;
8453         }
8454         // *w = 0; /* terminate class name */
8455  end:
8456         if (!info->name || !*info->name)
8457                 return 0;
8458         if (endptr)
8459                 *endptr = p;
8460         /* add other consistency checks */
8461         return 1;
8462 }
8463
8464
8465 /**
8466  * mono_identifier_unescape_type_name_chars:
8467  * @identifier: the display name of a mono type
8468  *
8469  * Returns:
8470  *  The name in internal form, that is without escaping backslashes.
8471  *
8472  *  The string is modified in place!
8473  */
8474 char*
8475 mono_identifier_unescape_type_name_chars(char* identifier)
8476 {
8477         char *w, *r;
8478         if (!identifier)
8479                 return NULL;
8480         for (w = r = identifier; *r != 0; r++)
8481         {
8482                 char c = *r;
8483                 if (c == '\\') {
8484                         r++;
8485                         if (*r == 0)
8486                                 break;
8487                         c = *r;
8488                 }
8489                 *w = c;
8490                 w++;
8491         }
8492         if (w != r)
8493                 *w = 0;
8494         return identifier;
8495 }
8496
8497 void
8498 mono_identifier_unescape_info (MonoTypeNameParse* info);
8499
8500 static void
8501 unescape_each_type_argument(void* data, void* user_data)
8502 {
8503         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8504         mono_identifier_unescape_info (info);
8505 }
8506
8507 static void
8508 unescape_each_nested_name (void* data, void* user_data)
8509 {
8510         char* nested_name = (char*) data;
8511         mono_identifier_unescape_type_name_chars(nested_name);
8512 }
8513
8514 /**
8515  * mono_identifier_unescape_info:
8516  *
8517  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8518  *
8519  * Returns: nothing.
8520  *
8521  * Destructively updates the info by unescaping the identifiers that
8522  * comprise the type namespace, name, nested types (if any) and
8523  * generic type arguments (if any).
8524  *
8525  * The resulting info has the names in internal form.
8526  *
8527  */
8528 void
8529 mono_identifier_unescape_info (MonoTypeNameParse *info)
8530 {
8531         if (!info)
8532                 return;
8533         mono_identifier_unescape_type_name_chars(info->name_space);
8534         mono_identifier_unescape_type_name_chars(info->name);
8535         // but don't escape info->assembly
8536         if (info->type_arguments)
8537                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8538         if (info->nested)
8539                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8540 }
8541
8542 int
8543 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8544 {
8545         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8546         if (ok) {
8547                 mono_identifier_unescape_info (info);
8548         }
8549         return ok;
8550 }
8551
8552 static MonoType*
8553 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8554 {
8555         gboolean type_resolve = FALSE;
8556         MonoType *type;
8557         MonoImage *rootimage = image;
8558
8559         mono_error_init (error);
8560
8561         if (info->assembly.name) {
8562                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8563                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8564                         /* 
8565                          * This could happen in the AOT compiler case when the search hook is not
8566                          * installed.
8567                          */
8568                         assembly = image->assembly;
8569                 if (!assembly) {
8570                         /* then we must load the assembly ourselve - see #60439 */
8571                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8572                         if (!assembly)
8573                                 return NULL;
8574                 }
8575                 image = assembly->image;
8576         } else if (!image) {
8577                 image = mono_defaults.corlib;
8578         }
8579
8580         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8581         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8582                 /* ignore the error and try again */
8583                 mono_error_cleanup (error);
8584                 mono_error_init (error);
8585                 image = mono_defaults.corlib;
8586                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8587         }
8588
8589         return type;
8590 }
8591
8592 /**
8593  * mono_reflection_get_type_internal:
8594  *
8595  * Returns: may return NULL on success, sets error on failure.
8596  */
8597 static MonoType*
8598 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8599 {
8600         MonoClass *klass;
8601         GList *mod;
8602         int modval;
8603         gboolean bounded = FALSE;
8604         
8605         mono_error_init (error);
8606         if (!image)
8607                 image = mono_defaults.corlib;
8608
8609         if (!rootimage)
8610                 rootimage = mono_defaults.corlib;
8611
8612         if (ignorecase)
8613                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8614         else
8615                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8616
8617         if (!klass)
8618                 return NULL;
8619
8620         for (mod = info->nested; mod; mod = mod->next) {
8621                 gpointer iter = NULL;
8622                 MonoClass *parent;
8623
8624                 parent = klass;
8625                 mono_class_init (parent);
8626
8627                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8628                         char *lastp;
8629                         char *nested_name, *nested_nspace;
8630                         gboolean match = TRUE;
8631
8632                         lastp = strrchr ((const char *)mod->data, '.');
8633                         if (lastp) {
8634                                 /* Nested classes can have namespaces */
8635                                 int nspace_len;
8636
8637                                 nested_name = g_strdup (lastp + 1);
8638                                 nspace_len = lastp - (char*)mod->data;
8639                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8640                                 memcpy (nested_nspace, mod->data, nspace_len);
8641                                 nested_nspace [nspace_len] = '\0';
8642
8643                         } else {
8644                                 nested_name = (char *)mod->data;
8645                                 nested_nspace = NULL;
8646                         }
8647
8648                         if (nested_nspace) {
8649                                 if (ignorecase) {
8650                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8651                                                 match = FALSE;
8652                                 } else {
8653                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8654                                                 match = FALSE;
8655                                 }
8656                         }
8657                         if (match) {
8658                                 if (ignorecase) {
8659                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8660                                                 match = FALSE;
8661                                 } else {
8662                                         if (strcmp (klass->name, nested_name) != 0)
8663                                                 match = FALSE;
8664                                 }
8665                         }
8666                         if (lastp) {
8667                                 g_free (nested_name);
8668                                 g_free (nested_nspace);
8669                         }
8670                         if (match)
8671                                 break;
8672                 }
8673
8674                 if (!klass)
8675                         break;
8676         }
8677         if (!klass)
8678                 return NULL;
8679
8680         if (info->type_arguments) {
8681                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8682                 MonoReflectionType *the_type;
8683                 MonoType *instance;
8684                 int i;
8685
8686                 for (i = 0; i < info->type_arguments->len; i++) {
8687                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8688
8689                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8690                         if (!type_args [i]) {
8691                                 g_free (type_args);
8692                                 return NULL;
8693                         }
8694                 }
8695
8696                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8697                 if (!the_type)
8698                         return NULL;
8699
8700                 instance = mono_reflection_bind_generic_parameters (
8701                         the_type, info->type_arguments->len, type_args, error);
8702
8703                 g_free (type_args);
8704                 if (!instance)
8705                         return NULL;
8706
8707                 klass = mono_class_from_mono_type (instance);
8708         }
8709
8710         for (mod = info->modifiers; mod; mod = mod->next) {
8711                 modval = GPOINTER_TO_UINT (mod->data);
8712                 if (!modval) { /* byref: must be last modifier */
8713                         return &klass->this_arg;
8714                 } else if (modval == -1) {
8715                         klass = mono_ptr_class_get (&klass->byval_arg);
8716                 } else if (modval == -2) {
8717                         bounded = TRUE;
8718                 } else { /* array rank */
8719                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8720                 }
8721         }
8722
8723         return &klass->byval_arg;
8724 }
8725
8726 /*
8727  * mono_reflection_get_type:
8728  * @image: a metadata context
8729  * @info: type description structure
8730  * @ignorecase: flag for case-insensitive string compares
8731  * @type_resolve: whenever type resolve was already tried
8732  *
8733  * Build a MonoType from the type description in @info.
8734  * 
8735  */
8736
8737 MonoType*
8738 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8739         MonoError error;
8740         MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8741         mono_error_cleanup (&error);
8742         return result;
8743 }
8744
8745 /**
8746  * mono_reflection_get_type_checked:
8747  * @rootimage: the image of the currently active managed caller
8748  * @image: a metadata context
8749  * @info: type description structure
8750  * @ignorecase: flag for case-insensitive string compares
8751  * @type_resolve: whenever type resolve was already tried
8752  * @error: set on error.
8753  *
8754  * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8755  *
8756  */
8757 MonoType*
8758 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8759         mono_error_init (error);
8760         return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
8761 }
8762
8763
8764 static MonoType*
8765 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8766 {
8767         MonoReflectionAssemblyBuilder *abuilder;
8768         MonoType *type;
8769         int i;
8770
8771         mono_error_init (error);
8772         g_assert (assembly_is_dynamic (assembly));
8773         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8774         if (!abuilder)
8775                 return NULL;
8776
8777         /* Enumerate all modules */
8778
8779         type = NULL;
8780         if (abuilder->modules) {
8781                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8782                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8783                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8784                         if (type)
8785                                 break;
8786                         if (!mono_error_ok (error))
8787                                 return NULL;
8788                 }
8789         }
8790
8791         if (!type && abuilder->loaded_modules) {
8792                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8793                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8794                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8795                         if (type)
8796                                 break;
8797                         if (!mono_error_ok (error))
8798                                 return NULL;
8799                 }
8800         }
8801
8802         return type;
8803 }
8804         
8805 MonoType*
8806 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8807 {
8808         MonoType *type;
8809         MonoReflectionAssembly *assembly;
8810         GString *fullName;
8811         GList *mod;
8812
8813         mono_error_init (error);
8814
8815         if (image && image_is_dynamic (image))
8816                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8817         else {
8818                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8819         }
8820         return_val_if_nok (error, NULL);
8821
8822         if (type)
8823                 return type;
8824         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8825                 return NULL;
8826
8827         if (type_resolve) {
8828                 if (*type_resolve) 
8829                         return NULL;
8830                 else
8831                         *type_resolve = TRUE;
8832         }
8833         
8834         /* Reconstruct the type name */
8835         fullName = g_string_new ("");
8836         if (info->name_space && (info->name_space [0] != '\0'))
8837                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8838         else
8839                 g_string_printf (fullName, "%s", info->name);
8840         for (mod = info->nested; mod; mod = mod->next)
8841                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8842
8843         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8844         if (!is_ok (error)) {
8845                 g_string_free (fullName, TRUE);
8846                 return NULL;
8847         }
8848
8849         if (assembly) {
8850                 if (assembly_is_dynamic (assembly->assembly))
8851                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8852                                                                           info, ignorecase, error);
8853                 else
8854                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8855                                                                   info, ignorecase, error);
8856         }
8857         g_string_free (fullName, TRUE);
8858         return_val_if_nok (error, NULL);
8859         return type;
8860 }
8861
8862 void
8863 mono_reflection_free_type_info (MonoTypeNameParse *info)
8864 {
8865         g_list_free (info->modifiers);
8866         g_list_free (info->nested);
8867
8868         if (info->type_arguments) {
8869                 int i;
8870
8871                 for (i = 0; i < info->type_arguments->len; i++) {
8872                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8873
8874                         mono_reflection_free_type_info (subinfo);
8875                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8876                         g_free (subinfo);
8877                 }
8878
8879                 g_ptr_array_free (info->type_arguments, TRUE);
8880         }
8881 }
8882
8883 /*
8884  * mono_reflection_type_from_name:
8885  * @name: type name.
8886  * @image: a metadata context (can be NULL).
8887  *
8888  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8889  * it defaults to get the type from @image or, if @image is NULL or loading
8890  * from it fails, uses corlib.
8891  * 
8892  */
8893 MonoType*
8894 mono_reflection_type_from_name (char *name, MonoImage *image)
8895 {
8896         MonoError error;
8897         MonoType  *result = mono_reflection_type_from_name_checked (name, image, &error);
8898         mono_error_cleanup (&error);
8899         return result;
8900 }
8901
8902 /**
8903  * mono_reflection_type_from_name_checked:
8904  * @name: type name.
8905  * @image: a metadata context (can be NULL).
8906  * @error: set on errror.
8907  *
8908  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8909  * it defaults to get the type from @image or, if @image is NULL or loading
8910  * from it fails, uses corlib.  On failure returns NULL and sets @error.
8911  * 
8912  */
8913 MonoType*
8914 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8915 {
8916         MonoType *type = NULL;
8917         MonoTypeNameParse info;
8918         char *tmp;
8919
8920         mono_error_init (error);
8921         /* Make a copy since parse_type modifies its argument */
8922         tmp = g_strdup (name);
8923         
8924         /*g_print ("requested type %s\n", str);*/
8925         if (mono_reflection_parse_type (tmp, &info)) {
8926                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8927                 if (!is_ok (error)) {
8928                         g_free (tmp);
8929                         mono_reflection_free_type_info (&info);
8930                         return NULL;
8931                 }
8932         }
8933
8934         g_free (tmp);
8935         mono_reflection_free_type_info (&info);
8936         return type;
8937 }
8938
8939 /*
8940  * mono_reflection_get_token:
8941  *
8942  *   Return the metadata token of OBJ which should be an object
8943  * representing a metadata element.
8944  */
8945 guint32
8946 mono_reflection_get_token (MonoObject *obj)
8947 {
8948         MonoError error;
8949         guint32 result = mono_reflection_get_token_checked (obj, &error);
8950         mono_error_assert_ok (&error);
8951         return result;
8952 }
8953
8954 /**
8955  * mono_reflection_get_token_checked:
8956  * @obj: the object
8957  * @error: set on error
8958  *
8959  *   Return the metadata token of @obj which should be an object
8960  * representing a metadata element.  On failure sets @error.
8961  */
8962 guint32
8963 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8964 {
8965         MonoClass *klass;
8966         guint32 token = 0;
8967
8968         mono_error_init (error);
8969
8970         klass = obj->vtable->klass;
8971
8972         if (strcmp (klass->name, "MethodBuilder") == 0) {
8973                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8974
8975                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8976         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8977                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8978
8979                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8980         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8981                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8982
8983                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8984         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8985                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8986                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8987         } else if (strcmp (klass->name, "RuntimeType") == 0) {
8988                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8989                 return_val_if_nok (error, 0);
8990                 MonoClass *mc = mono_class_from_mono_type (type);
8991                 if (!mono_class_init (mc)) {
8992                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8993                         return 0;
8994                 }
8995
8996                 token = mc->type_token;
8997         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8998                    strcmp (klass->name, "MonoMethod") == 0 ||
8999                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
9000                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
9001                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
9002                 if (m->method->is_inflated) {
9003                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
9004                         return inflated->declaring->token;
9005                 } else {
9006                         token = m->method->token;
9007                 }
9008         } else if (strcmp (klass->name, "MonoField") == 0) {
9009                 MonoReflectionField *f = (MonoReflectionField*)obj;
9010
9011                 if (is_field_on_inst (f->field)) {
9012                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
9013
9014                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
9015                                 int field_index = f->field - dgclass->fields;
9016                                 MonoObject *obj;
9017
9018                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
9019                                 obj = dgclass->field_objects [field_index];
9020                                 return mono_reflection_get_token_checked (obj, error);
9021                         }
9022                 }
9023                 token = mono_class_get_field_token (f->field);
9024         } else if (strcmp (klass->name, "MonoProperty") == 0) {
9025                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
9026
9027                 token = mono_class_get_property_token (p->property);
9028         } else if (strcmp (klass->name, "MonoEvent") == 0) {
9029                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
9030
9031                 token = mono_class_get_event_token (p->event);
9032         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
9033                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
9034                 MonoClass *member_class = mono_object_class (p->MemberImpl);
9035                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
9036
9037                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
9038         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
9039                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
9040
9041                 token = m->token;
9042         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
9043                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
9044         } else {
9045                 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
9046                                                 klass->name_space, klass->name);
9047                 return 0;
9048         }
9049
9050         return token;
9051 }
9052
9053 /*
9054  * Load the type with name @n on behalf of image @image.  On failure sets @error and returns NULL.
9055  * The @is_enum flag only affects the error message that's displayed on failure.
9056  */
9057 static MonoType*
9058 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
9059 {
9060         MonoError inner_error;
9061         MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
9062         if (!t) {
9063                 mono_error_set_type_load_name (error, g_strdup(n), NULL,
9064                                                "Could not load %s %s while decoding custom attribute: %s",
9065                                                is_enum ? "enum type": "type",
9066                                                n,
9067                                                mono_error_get_message (&inner_error));
9068                 mono_error_cleanup (&inner_error);
9069                 return NULL;
9070         }
9071         return t;
9072 }
9073
9074 static MonoClass*
9075 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
9076 {
9077         char *n;
9078         MonoType *t;
9079         int slen = mono_metadata_decode_value (p, &p);
9080
9081         mono_error_init (error);
9082
9083         n = (char *)g_memdup (p, slen + 1);
9084         n [slen] = 0;
9085         t = cattr_type_from_name (n, image, TRUE, error);
9086         g_free (n);
9087         return_val_if_nok (error, NULL);
9088         p += slen;
9089         *end = p;
9090         return mono_class_from_mono_type (t);
9091 }
9092
9093 static void*
9094 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
9095 {
9096         int slen, type = t->type;
9097         MonoClass *tklass = t->data.klass;
9098
9099         mono_error_init (error);
9100
9101 handle_enum:
9102         switch (type) {
9103         case MONO_TYPE_U1:
9104         case MONO_TYPE_I1:
9105         case MONO_TYPE_BOOLEAN: {
9106                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
9107                 *bval = *p;
9108                 *end = p + 1;
9109                 return bval;
9110         }
9111         case MONO_TYPE_CHAR:
9112         case MONO_TYPE_U2:
9113         case MONO_TYPE_I2: {
9114                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
9115                 *val = read16 (p);
9116                 *end = p + 2;
9117                 return val;
9118         }
9119 #if SIZEOF_VOID_P == 4
9120         case MONO_TYPE_U:
9121         case MONO_TYPE_I:
9122 #endif
9123         case MONO_TYPE_R4:
9124         case MONO_TYPE_U4:
9125         case MONO_TYPE_I4: {
9126                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9127                 *val = read32 (p);
9128                 *end = p + 4;
9129                 return val;
9130         }
9131 #if SIZEOF_VOID_P == 8
9132         case MONO_TYPE_U: /* error out instead? this should probably not happen */
9133         case MONO_TYPE_I:
9134 #endif
9135         case MONO_TYPE_U8:
9136         case MONO_TYPE_I8: {
9137                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9138                 *val = read64 (p);
9139                 *end = p + 8;
9140                 return val;
9141         }
9142         case MONO_TYPE_R8: {
9143                 double *val = (double *)g_malloc (sizeof (double));
9144                 readr8 (p, val);
9145                 *end = p + 8;
9146                 return val;
9147         }
9148         case MONO_TYPE_VALUETYPE:
9149                 if (t->data.klass->enumtype) {
9150                         type = mono_class_enum_basetype (t->data.klass)->type;
9151                         goto handle_enum;
9152                 } else {
9153                         MonoClass *k =  t->data.klass;
9154                         
9155                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9156                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9157                                 *val = read64 (p);
9158                                 *end = p + 8;
9159                                 return val;
9160                         }
9161                 }
9162                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9163                 break;
9164                 
9165         case MONO_TYPE_STRING:
9166                 if (*p == (char)0xFF) {
9167                         *end = p + 1;
9168                         return NULL;
9169                 }
9170                 slen = mono_metadata_decode_value (p, &p);
9171                 *end = p + slen;
9172                 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
9173         case MONO_TYPE_CLASS: {
9174                 MonoReflectionType *rt;
9175                 char *n;
9176                 MonoType *t;
9177                 if (*p == (char)0xFF) {
9178                         *end = p + 1;
9179                         return NULL;
9180                 }
9181 handle_type:
9182                 slen = mono_metadata_decode_value (p, &p);
9183                 n = (char *)g_memdup (p, slen + 1);
9184                 n [slen] = 0;
9185                 t = cattr_type_from_name (n, image, FALSE, error);
9186                 g_free (n);
9187                 return_val_if_nok (error, NULL);
9188                 *end = p + slen;
9189
9190                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9191                 if (!mono_error_ok (error))
9192                         return NULL;
9193
9194                 return rt;
9195         }
9196         case MONO_TYPE_OBJECT: {
9197                 char subt = *p++;
9198                 MonoObject *obj;
9199                 MonoClass *subc = NULL;
9200                 void *val;
9201
9202                 if (subt == 0x50) {
9203                         goto handle_type;
9204                 } else if (subt == 0x0E) {
9205                         type = MONO_TYPE_STRING;
9206                         goto handle_enum;
9207                 } else if (subt == 0x1D) {
9208                         MonoType simple_type = {{0}};
9209                         int etype = *p;
9210                         p ++;
9211
9212                         type = MONO_TYPE_SZARRAY;
9213                         if (etype == 0x50) {
9214                                 tklass = mono_defaults.systemtype_class;
9215                         } else if (etype == 0x55) {
9216                                 tklass = load_cattr_enum_type (image, p, &p, error);
9217                                 if (!mono_error_ok (error))
9218                                         return NULL;
9219                         } else {
9220                                 if (etype == 0x51)
9221                                         /* See Partition II, Appendix B3 */
9222                                         etype = MONO_TYPE_OBJECT;
9223                                 simple_type.type = (MonoTypeEnum)etype;
9224                                 tklass = mono_class_from_mono_type (&simple_type);
9225                         }
9226                         goto handle_enum;
9227                 } else if (subt == 0x55) {
9228                         char *n;
9229                         MonoType *t;
9230                         slen = mono_metadata_decode_value (p, &p);
9231                         n = (char *)g_memdup (p, slen + 1);
9232                         n [slen] = 0;
9233                         t = cattr_type_from_name (n, image, FALSE, error);
9234                         g_free (n);
9235                         return_val_if_nok (error, NULL);
9236                         p += slen;
9237                         subc = mono_class_from_mono_type (t);
9238                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9239                         MonoType simple_type = {{0}};
9240                         simple_type.type = (MonoTypeEnum)subt;
9241                         subc = mono_class_from_mono_type (&simple_type);
9242                 } else {
9243                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9244                 }
9245                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9246                 obj = NULL;
9247                 if (mono_error_ok (error)) {
9248                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
9249                         g_assert (!subc->has_references);
9250                         if (mono_error_ok (error))
9251                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9252                 }
9253
9254                 g_free (val);
9255                 return obj;
9256         }
9257         case MONO_TYPE_SZARRAY: {
9258                 MonoArray *arr;
9259                 guint32 i, alen, basetype;
9260                 alen = read32 (p);
9261                 p += 4;
9262                 if (alen == 0xffffffff) {
9263                         *end = p;
9264                         return NULL;
9265                 }
9266                 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
9267                 return_val_if_nok (error, NULL);
9268                 basetype = tklass->byval_arg.type;
9269                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9270                         basetype = mono_class_enum_basetype (tklass)->type;
9271                 switch (basetype)
9272                 {
9273                         case MONO_TYPE_U1:
9274                         case MONO_TYPE_I1:
9275                         case MONO_TYPE_BOOLEAN:
9276                                 for (i = 0; i < alen; i++) {
9277                                         MonoBoolean val = *p++;
9278                                         mono_array_set (arr, MonoBoolean, i, val);
9279                                 }
9280                                 break;
9281                         case MONO_TYPE_CHAR:
9282                         case MONO_TYPE_U2:
9283                         case MONO_TYPE_I2:
9284                                 for (i = 0; i < alen; i++) {
9285                                         guint16 val = read16 (p);
9286                                         mono_array_set (arr, guint16, i, val);
9287                                         p += 2;
9288                                 }
9289                                 break;
9290                         case MONO_TYPE_R4:
9291                         case MONO_TYPE_U4:
9292                         case MONO_TYPE_I4:
9293                                 for (i = 0; i < alen; i++) {
9294                                         guint32 val = read32 (p);
9295                                         mono_array_set (arr, guint32, i, val);
9296                                         p += 4;
9297                                 }
9298                                 break;
9299                         case MONO_TYPE_R8:
9300                                 for (i = 0; i < alen; i++) {
9301                                         double val;
9302                                         readr8 (p, &val);
9303                                         mono_array_set (arr, double, i, val);
9304                                         p += 8;
9305                                 }
9306                                 break;
9307                         case MONO_TYPE_U8:
9308                         case MONO_TYPE_I8:
9309                                 for (i = 0; i < alen; i++) {
9310                                         guint64 val = read64 (p);
9311                                         mono_array_set (arr, guint64, i, val);
9312                                         p += 8;
9313                                 }
9314                                 break;
9315                         case MONO_TYPE_CLASS:
9316                         case MONO_TYPE_OBJECT:
9317                         case MONO_TYPE_STRING:
9318                         case MONO_TYPE_SZARRAY:
9319                                 for (i = 0; i < alen; i++) {
9320                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9321                                         if (!mono_error_ok (error))
9322                                                 return NULL;
9323                                         mono_array_setref (arr, i, item);
9324                                 }
9325                                 break;
9326                         default:
9327                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9328                 }
9329                 *end=p;
9330                 return arr;
9331         }
9332         default:
9333                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9334         }
9335         return NULL;
9336 }
9337
9338 static MonoObject*
9339 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9340 {
9341         mono_error_init (error);
9342
9343         gboolean is_ref = type_is_reference (t);
9344
9345         void *val = load_cattr_value (image, t, p, end, error);
9346         if (!is_ok (error)) {
9347                 if (is_ref)
9348                         g_free (val);
9349                 return NULL;
9350         }
9351
9352         if (is_ref)
9353                 return (MonoObject*)val;
9354
9355         MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9356         g_free (val);
9357         return boxed;
9358 }
9359
9360 static MonoObject*
9361 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9362 {
9363         static MonoMethod *ctor;
9364         MonoObject *retval;
9365         void *params [2], *unboxed;
9366
9367         mono_error_init (error);
9368
9369         if (!ctor)
9370                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9371         
9372         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9373         return_val_if_nok (error, NULL);
9374
9375         params [1] = val;
9376         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9377         return_val_if_nok (error, NULL);
9378         unboxed = mono_object_unbox (retval);
9379
9380         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9381         return_val_if_nok (error, NULL);
9382
9383         return retval;
9384 }
9385
9386 static MonoObject*
9387 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9388 {
9389         static MonoMethod *ctor;
9390         MonoObject *retval;
9391         void *unboxed, *params [2];
9392
9393         mono_error_init (error);
9394
9395         if (!ctor)
9396                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9397
9398         params [0] = minfo;
9399         params [1] = typedarg;
9400         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9401         return_val_if_nok (error, NULL);
9402
9403         unboxed = mono_object_unbox (retval);
9404
9405         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9406         return_val_if_nok (error, NULL);
9407
9408         return retval;
9409 }
9410
9411 static gboolean
9412 type_is_reference (MonoType *type)
9413 {
9414         switch (type->type) {
9415         case MONO_TYPE_BOOLEAN:
9416         case MONO_TYPE_CHAR:
9417         case MONO_TYPE_U:
9418         case MONO_TYPE_I:
9419         case MONO_TYPE_U1:
9420         case MONO_TYPE_I1:
9421         case MONO_TYPE_U2:
9422         case MONO_TYPE_I2:
9423         case MONO_TYPE_U4:
9424         case MONO_TYPE_I4:
9425         case MONO_TYPE_U8:
9426         case MONO_TYPE_I8:
9427         case MONO_TYPE_R8:
9428         case MONO_TYPE_R4:
9429         case MONO_TYPE_VALUETYPE:
9430                 return FALSE;
9431         default:
9432                 return TRUE;
9433         }
9434 }
9435
9436 static void
9437 free_param_data (MonoMethodSignature *sig, void **params) {
9438         int i;
9439         for (i = 0; i < sig->param_count; ++i) {
9440                 if (!type_is_reference (sig->params [i]))
9441                         g_free (params [i]);
9442         }
9443 }
9444
9445 /*
9446  * Find the field index in the metadata FieldDef table.
9447  */
9448 static guint32
9449 find_field_index (MonoClass *klass, MonoClassField *field) {
9450         int i;
9451
9452         for (i = 0; i < klass->field.count; ++i) {
9453                 if (field == &klass->fields [i])
9454                         return klass->field.first + 1 + i;
9455         }
9456         return 0;
9457 }
9458
9459 /*
9460  * Find the property index in the metadata Property table.
9461  */
9462 static guint32
9463 find_property_index (MonoClass *klass, MonoProperty *property) {
9464         int i;
9465
9466         for (i = 0; i < klass->ext->property.count; ++i) {
9467                 if (property == &klass->ext->properties [i])
9468                         return klass->ext->property.first + 1 + i;
9469         }
9470         return 0;
9471 }
9472
9473 /*
9474  * Find the event index in the metadata Event table.
9475  */
9476 static guint32
9477 find_event_index (MonoClass *klass, MonoEvent *event) {
9478         int i;
9479
9480         for (i = 0; i < klass->ext->event.count; ++i) {
9481                 if (event == &klass->ext->events [i])
9482                         return klass->ext->event.first + 1 + i;
9483         }
9484         return 0;
9485 }
9486
9487 static MonoObject*
9488 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9489 {
9490         const char *p = (const char*)data;
9491         const char *named;
9492         guint32 i, j, num_named;
9493         MonoObject *attr;
9494         void *params_buf [32];
9495         void **params = NULL;
9496         MonoMethodSignature *sig;
9497
9498         mono_error_init (error);
9499
9500         mono_class_init (method->klass);
9501
9502         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9503                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9504                 return NULL;
9505         }
9506
9507         if (len == 0) {
9508                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9509                 if (!mono_error_ok (error)) return NULL;
9510
9511                 mono_runtime_invoke_checked (method, attr, NULL, error);
9512                 if (!mono_error_ok (error))
9513                         return NULL;
9514
9515                 return attr;
9516         }
9517
9518         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9519                 return NULL;
9520
9521         /*g_print ("got attr %s\n", method->klass->name);*/
9522
9523         sig = mono_method_signature (method);
9524         if (sig->param_count < 32) {
9525                 params = params_buf;
9526                 memset (params, 0, sizeof (void*) * sig->param_count);
9527         } else {
9528                 /* Allocate using GC so it gets GC tracking */
9529                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9530         }
9531
9532         /* skip prolog */
9533         p += 2;
9534         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9535                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9536                 if (!mono_error_ok (error))
9537                         goto fail;
9538         }
9539
9540         named = p;
9541         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9542         if (!mono_error_ok (error)) goto fail;
9543
9544         MonoObject *exc = NULL;
9545         mono_runtime_try_invoke (method, attr, params, &exc, error);
9546         if (!mono_error_ok (error))
9547                 goto fail;
9548         if (exc) {
9549                 mono_error_set_exception_instance (error, (MonoException*)exc);
9550                 goto fail;
9551         }
9552
9553         num_named = read16 (named);
9554         named += 2;
9555         for (j = 0; j < num_named; j++) {
9556                 gint name_len;
9557                 char *name, named_type, data_type;
9558                 named_type = *named++;
9559                 data_type = *named++; /* type of data */
9560                 if (data_type == MONO_TYPE_SZARRAY)
9561                         data_type = *named++;
9562                 if (data_type == MONO_TYPE_ENUM) {
9563                         gint type_len;
9564                         char *type_name;
9565                         type_len = mono_metadata_decode_blob_size (named, &named);
9566                         type_name = (char *)g_malloc (type_len + 1);
9567                         memcpy (type_name, named, type_len);
9568                         type_name [type_len] = 0;
9569                         named += type_len;
9570                         /* FIXME: lookup the type and check type consistency */
9571                         g_free (type_name);
9572                 }
9573                 name_len = mono_metadata_decode_blob_size (named, &named);
9574                 name = (char *)g_malloc (name_len + 1);
9575                 memcpy (name, named, name_len);
9576                 name [name_len] = 0;
9577                 named += name_len;
9578                 if (named_type == 0x53) {
9579                         MonoClassField *field;
9580                         void *val;
9581
9582                         /* how this fail is a blackbox */
9583                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9584                         if (!field) {
9585                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9586                                 g_free (name);
9587                                 goto fail;
9588                         }
9589
9590                         val = load_cattr_value (image, field->type, named, &named, error);
9591                         if (!mono_error_ok (error)) {
9592                                 g_free (name);
9593                                 if (!type_is_reference (field->type))
9594                                         g_free (val);
9595                                 goto fail;
9596                         }
9597
9598                         mono_field_set_value (attr, field, val);
9599                         if (!type_is_reference (field->type))
9600                                 g_free (val);
9601                 } else if (named_type == 0x54) {
9602                         MonoProperty *prop;
9603                         void *pparams [1];
9604                         MonoType *prop_type;
9605
9606                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9607
9608                         if (!prop) {
9609                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9610                                 g_free (name);
9611                                 goto fail;
9612                         }
9613
9614                         if (!prop->set) {
9615                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9616                                 g_free (name);
9617                                 goto fail;
9618                         }
9619
9620                         /* can we have more that 1 arg in a custom attr named property? */
9621                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9622                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9623
9624                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9625                         if (!mono_error_ok (error)) {
9626                                 g_free (name);
9627                                 if (!type_is_reference (prop_type))
9628                                         g_free (pparams [0]);
9629                                 goto fail;
9630                         }
9631
9632
9633                         mono_property_set_value_checked (prop, attr, pparams, error);
9634                         if (!type_is_reference (prop_type))
9635                                 g_free (pparams [0]);
9636                         if (!is_ok (error)) {
9637                                 g_free (name);
9638                                 goto fail;
9639                         }
9640                 }
9641                 g_free (name);
9642         }
9643
9644         free_param_data (method->signature, params);
9645         if (params != params_buf)
9646                 mono_gc_free_fixed (params);
9647
9648         return attr;
9649
9650 fail:
9651         free_param_data (method->signature, params);
9652         if (params != params_buf)
9653                 mono_gc_free_fixed (params);
9654         return NULL;
9655 }
9656         
9657 /*
9658  * mono_reflection_create_custom_attr_data_args:
9659  *
9660  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9661  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9662  * NAMED_ARG_INFO will contain information about the named arguments.
9663  */
9664 void
9665 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)
9666 {
9667         MonoArray *typedargs, *namedargs;
9668         MonoClass *attrklass;
9669         MonoDomain *domain;
9670         const char *p = (const char*)data;
9671         const char *named;
9672         guint32 i, j, num_named;
9673         CattrNamedArg *arginfo = NULL;
9674
9675         *typed_args = NULL;
9676         *named_args = NULL;
9677         *named_arg_info = NULL;
9678
9679         mono_error_init (error);
9680
9681         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9682                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9683                 return;
9684         }
9685
9686         mono_class_init (method->klass);
9687         
9688         domain = mono_domain_get ();
9689
9690         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9691                 return;
9692
9693         typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
9694         return_if_nok (error);
9695
9696         /* skip prolog */
9697         p += 2;
9698         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9699                 MonoObject *obj;
9700
9701                 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9702                 return_if_nok (error);
9703                 mono_array_setref (typedargs, i, obj);
9704         }
9705
9706         named = p;
9707         num_named = read16 (named);
9708         namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
9709         return_if_nok (error);
9710         named += 2;
9711         attrklass = method->klass;
9712
9713         arginfo = g_new0 (CattrNamedArg, num_named);
9714         *named_arg_info = arginfo;
9715
9716         for (j = 0; j < num_named; j++) {
9717                 gint name_len;
9718                 char *name, named_type, data_type;
9719                 named_type = *named++;
9720                 data_type = *named++; /* type of data */
9721                 if (data_type == MONO_TYPE_SZARRAY)
9722                         data_type = *named++;
9723                 if (data_type == MONO_TYPE_ENUM) {
9724                         gint type_len;
9725                         char *type_name;
9726                         type_len = mono_metadata_decode_blob_size (named, &named);
9727                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9728                                 goto fail;
9729
9730                         type_name = (char *)g_malloc (type_len + 1);
9731                         memcpy (type_name, named, type_len);
9732                         type_name [type_len] = 0;
9733                         named += type_len;
9734                         /* FIXME: lookup the type and check type consistency */
9735                         g_free (type_name);
9736                 }
9737                 name_len = mono_metadata_decode_blob_size (named, &named);
9738                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9739                         goto fail;
9740                 name = (char *)g_malloc (name_len + 1);
9741                 memcpy (name, named, name_len);
9742                 name [name_len] = 0;
9743                 named += name_len;
9744                 if (named_type == 0x53) {
9745                         MonoObject *obj;
9746                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9747
9748                         if (!field) {
9749                                 g_free (name);
9750                                 goto fail;
9751                         }
9752
9753                         arginfo [j].type = field->type;
9754                         arginfo [j].field = field;
9755
9756                         obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9757                         if (!is_ok (error)) {
9758                                 g_free (name);
9759                                 return;
9760                         }
9761                         mono_array_setref (namedargs, j, obj);
9762
9763                 } else if (named_type == 0x54) {
9764                         MonoObject *obj;
9765                         MonoType *prop_type;
9766                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9767
9768                         if (!prop || !prop->set) {
9769                                 g_free (name);
9770                                 goto fail;
9771                         }
9772
9773                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9774                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9775
9776                         arginfo [j].type = prop_type;
9777                         arginfo [j].prop = prop;
9778
9779                         obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9780                         if (!is_ok (error)) {
9781                                 g_free (name);
9782                                 return;
9783                         }
9784                         mono_array_setref (namedargs, j, obj);
9785                 }
9786                 g_free (name);
9787         }
9788
9789         *typed_args = typedargs;
9790         *named_args = namedargs;
9791         return;
9792 fail:
9793         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9794         g_free (arginfo);
9795         *named_arg_info = NULL;
9796 }
9797
9798 static gboolean
9799 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
9800 {
9801         MonoDomain *domain;
9802         MonoArray *typedargs, *namedargs;
9803         MonoImage *image;
9804         MonoMethod *method;
9805         CattrNamedArg *arginfo = NULL;
9806         int i;
9807
9808         mono_error_init (error);
9809
9810         *ctor_args = NULL;
9811         *named_args = NULL;
9812
9813         if (len == 0)
9814                 return TRUE;
9815
9816         image = assembly->assembly->image;
9817         method = ref_method->method;
9818         domain = mono_object_domain (ref_method);
9819
9820         if (!mono_class_init (method->klass)) {
9821                 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (method->klass));
9822                 goto leave;
9823         }
9824
9825         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
9826         if (!is_ok (error))
9827                 goto leave;
9828
9829         if (!typedargs || !namedargs)
9830                 goto leave;
9831
9832         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9833                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9834                 MonoObject *typedarg;
9835
9836                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
9837                 if (!is_ok (error))
9838                         goto leave;
9839                 mono_array_setref (typedargs, i, typedarg);
9840         }
9841
9842         for (i = 0; i < mono_array_length (namedargs); ++i) {
9843                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9844                 MonoObject *typedarg, *namedarg, *minfo;
9845
9846                 if (arginfo [i].prop) {
9847                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
9848                         if (!minfo)
9849                                 goto leave;
9850                 } else {
9851                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
9852                         if (!is_ok (error))
9853                                 goto leave;
9854                 }
9855
9856                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
9857                 if (!is_ok (error))
9858                         goto leave;
9859                 namedarg = create_cattr_named_arg (minfo, typedarg, error);
9860                 if (!is_ok (error))
9861                         goto leave;
9862
9863                 mono_array_setref (namedargs, i, namedarg);
9864         }
9865
9866         *ctor_args = typedargs;
9867         *named_args = namedargs;
9868
9869 leave:
9870         g_free (arginfo);
9871         return mono_error_ok (error);
9872 }
9873
9874 void
9875 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9876 {
9877         MonoError error;
9878         (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
9879         mono_error_set_pending_exception (&error);
9880 }
9881
9882 static MonoObject*
9883 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9884 {
9885         static MonoMethod *ctor;
9886
9887         MonoDomain *domain;
9888         MonoObject *attr;
9889         void *params [4];
9890
9891         mono_error_init (error);
9892
9893         g_assert (image->assembly);
9894
9895         if (!ctor)
9896                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9897
9898         domain = mono_domain_get ();
9899         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9900         return_val_if_nok (error, NULL);
9901         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9902         return_val_if_nok (error, NULL);
9903         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9904         return_val_if_nok (error, NULL);
9905         params [2] = (gpointer)&cattr->data;
9906         params [3] = &cattr->data_size;
9907
9908         mono_runtime_invoke_checked (ctor, attr, params, error);
9909         return_val_if_nok (error, NULL);
9910         return attr;
9911 }
9912
9913 static MonoArray*
9914 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9915 {
9916         MonoArray *result;
9917         MonoObject *attr;
9918         int i, n;
9919
9920         mono_error_init (error);
9921
9922         n = 0;
9923         for (i = 0; i < cinfo->num_attrs; ++i) {
9924                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9925                         n ++;
9926         }
9927
9928         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
9929         return_val_if_nok (error, NULL);
9930         n = 0;
9931         for (i = 0; i < cinfo->num_attrs; ++i) {
9932                 if (!cinfo->attrs [i].ctor) {
9933                         /* The cattr type is not finished yet */
9934                         /* We should include the type name but cinfo doesn't contain it */
9935                         mono_error_set_type_load_name (error, NULL, NULL, "");
9936                         return NULL;
9937                 }
9938                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9939                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9940                         if (!mono_error_ok (error))
9941                                 return result;
9942                         mono_array_setref (result, n, attr);
9943                         n ++;
9944                 }
9945         }
9946         return result;
9947 }
9948
9949 MonoArray*
9950 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9951 {
9952         MonoError error;
9953         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9954         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9955
9956         return result;
9957 }
9958
9959 static MonoArray*
9960 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9961 {
9962         MonoArray *result;
9963         MonoObject *attr;
9964         int i;
9965         
9966         mono_error_init (error);
9967         result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
9968         return_val_if_nok (error, NULL);
9969         for (i = 0; i < cinfo->num_attrs; ++i) {
9970                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9971                 return_val_if_nok (error, NULL);
9972                 mono_array_setref (result, i, attr);
9973         }
9974         return result;
9975 }
9976
9977 /**
9978  * mono_custom_attrs_from_index:
9979  *
9980  * Returns: NULL if no attributes are found or if a loading error occurs.
9981  */
9982 MonoCustomAttrInfo*
9983 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9984 {
9985         MonoError error;
9986         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9987         mono_error_cleanup (&error);
9988         return result;
9989 }
9990 /**
9991  * mono_custom_attrs_from_index_checked:
9992  *
9993  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9994  */
9995 MonoCustomAttrInfo*
9996 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9997 {
9998         guint32 mtoken, i, len;
9999         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
10000         MonoTableInfo *ca;
10001         MonoCustomAttrInfo *ainfo;
10002         GList *tmp, *list = NULL;
10003         const char *data;
10004         MonoCustomAttrEntry* attr;
10005
10006         mono_error_init (error);
10007
10008         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
10009
10010         i = mono_metadata_custom_attrs_from_index (image, idx);
10011         if (!i)
10012                 return NULL;
10013         i --;
10014         while (i < ca->rows) {
10015                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
10016                         break;
10017                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
10018                 ++i;
10019         }
10020         len = g_list_length (list);
10021         if (!len)
10022                 return NULL;
10023         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
10024         ainfo->num_attrs = len;
10025         ainfo->image = image;
10026         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
10027                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
10028                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
10029                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
10030                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
10031                         mtoken |= MONO_TOKEN_METHOD_DEF;
10032                         break;
10033                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
10034                         mtoken |= MONO_TOKEN_MEMBER_REF;
10035                         break;
10036                 default:
10037                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
10038                         break;
10039                 }
10040                 attr = &ainfo->attrs [i - 1];
10041                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
10042                 if (!attr->ctor) {
10043                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
10044                         g_list_free (list);
10045                         g_free (ainfo);
10046                         return NULL;
10047                 }
10048
10049                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
10050                         /*FIXME raising an exception here doesn't make any sense*/
10051                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
10052                         g_list_free (list);
10053                         g_free (ainfo);
10054                         return NULL;
10055                 }
10056                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
10057                 attr->data_size = mono_metadata_decode_value (data, &data);
10058                 attr->data = (guchar*)data;
10059         }
10060         g_list_free (list);
10061
10062         return ainfo;
10063 }
10064
10065 MonoCustomAttrInfo*
10066 mono_custom_attrs_from_method (MonoMethod *method)
10067 {
10068         MonoError error;
10069         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
10070         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10071         return result;
10072 }
10073
10074 MonoCustomAttrInfo*
10075 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
10076 {
10077         guint32 idx;
10078
10079         mono_error_init (error);
10080
10081         /*
10082          * An instantiated method has the same cattrs as the generic method definition.
10083          *
10084          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10085          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10086          */
10087         if (method->is_inflated)
10088                 method = ((MonoMethodInflated *) method)->declaring;
10089         
10090         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
10091                 return lookup_custom_attr (method->klass->image, method);
10092
10093         if (!method->token)
10094                 /* Synthetic methods */
10095                 return NULL;
10096
10097         idx = mono_method_get_index (method);
10098         idx <<= MONO_CUSTOM_ATTR_BITS;
10099         idx |= MONO_CUSTOM_ATTR_METHODDEF;
10100         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
10101 }
10102
10103 MonoCustomAttrInfo*
10104 mono_custom_attrs_from_class (MonoClass *klass)
10105 {
10106         MonoError error;
10107         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
10108         mono_error_cleanup (&error);
10109         return result;
10110 }
10111
10112 MonoCustomAttrInfo*
10113 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
10114 {
10115         guint32 idx;
10116
10117         mono_error_init (error);
10118
10119         if (klass->generic_class)
10120                 klass = klass->generic_class->container_class;
10121
10122         if (image_is_dynamic (klass->image))
10123                 return lookup_custom_attr (klass->image, klass);
10124
10125         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
10126                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
10127                 idx <<= MONO_CUSTOM_ATTR_BITS;
10128                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10129         } else {
10130                 idx = mono_metadata_token_index (klass->type_token);
10131                 idx <<= MONO_CUSTOM_ATTR_BITS;
10132                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10133         }
10134         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10135 }
10136
10137 MonoCustomAttrInfo*
10138 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10139 {
10140         MonoError error;
10141         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10142         mono_error_cleanup (&error);
10143         return result;
10144 }
10145
10146 MonoCustomAttrInfo*
10147 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10148 {
10149         guint32 idx;
10150         
10151         mono_error_init (error);
10152
10153         if (image_is_dynamic (assembly->image))
10154                 return lookup_custom_attr (assembly->image, assembly);
10155         idx = 1; /* there is only one assembly */
10156         idx <<= MONO_CUSTOM_ATTR_BITS;
10157         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10158         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10159 }
10160
10161 static MonoCustomAttrInfo*
10162 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10163 {
10164         guint32 idx;
10165         
10166         if (image_is_dynamic (image))
10167                 return lookup_custom_attr (image, image);
10168         idx = 1; /* there is only one module */
10169         idx <<= MONO_CUSTOM_ATTR_BITS;
10170         idx |= MONO_CUSTOM_ATTR_MODULE;
10171         return mono_custom_attrs_from_index_checked (image, idx, error);
10172 }
10173
10174 MonoCustomAttrInfo*
10175 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10176 {
10177         MonoError error;
10178         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10179         mono_error_cleanup (&error);
10180         return result;
10181 }
10182
10183 MonoCustomAttrInfo*
10184 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10185 {
10186         guint32 idx;
10187         
10188         if (image_is_dynamic (klass->image)) {
10189                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10190                 return lookup_custom_attr (klass->image, property);
10191         }
10192         idx = find_property_index (klass, property);
10193         idx <<= MONO_CUSTOM_ATTR_BITS;
10194         idx |= MONO_CUSTOM_ATTR_PROPERTY;
10195         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10196 }
10197
10198 MonoCustomAttrInfo*
10199 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10200 {
10201         MonoError error;
10202         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10203         mono_error_cleanup (&error);
10204         return result;
10205 }
10206
10207 MonoCustomAttrInfo*
10208 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10209 {
10210         guint32 idx;
10211         
10212         if (image_is_dynamic (klass->image)) {
10213                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10214                 return lookup_custom_attr (klass->image, event);
10215         }
10216         idx = find_event_index (klass, event);
10217         idx <<= MONO_CUSTOM_ATTR_BITS;
10218         idx |= MONO_CUSTOM_ATTR_EVENT;
10219         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10220 }
10221
10222 MonoCustomAttrInfo*
10223 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10224 {
10225         MonoError error;
10226         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10227         mono_error_cleanup (&error);
10228         return result;
10229 }
10230
10231 MonoCustomAttrInfo*
10232 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10233 {
10234         guint32 idx;
10235         mono_error_init (error);
10236
10237         if (image_is_dynamic (klass->image)) {
10238                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10239                 return lookup_custom_attr (klass->image, field);
10240         }
10241         idx = find_field_index (klass, field);
10242         idx <<= MONO_CUSTOM_ATTR_BITS;
10243         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10244         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10245 }
10246
10247 /**
10248  * mono_custom_attrs_from_param:
10249  * @method: handle to the method that we want to retrieve custom parameter information from
10250  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10251  *
10252  * The result must be released with mono_custom_attrs_free().
10253  *
10254  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10255  */
10256 MonoCustomAttrInfo*
10257 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10258 {
10259         MonoError error;
10260         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10261         mono_error_cleanup (&error);
10262         return result;
10263 }
10264
10265 /**
10266  * mono_custom_attrs_from_param_checked:
10267  * @method: handle to the method that we want to retrieve custom parameter information from
10268  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10269  * @error: set on error
10270  *
10271  * The result must be released with mono_custom_attrs_free().
10272  *
10273  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
10274  */
10275 MonoCustomAttrInfo*
10276 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10277 {
10278         MonoTableInfo *ca;
10279         guint32 i, idx, method_index;
10280         guint32 param_list, param_last, param_pos, found;
10281         MonoImage *image;
10282         MonoReflectionMethodAux *aux;
10283
10284         mono_error_init (error);
10285
10286         /*
10287          * An instantiated method has the same cattrs as the generic method definition.
10288          *
10289          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10290          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10291          */
10292         if (method->is_inflated)
10293                 method = ((MonoMethodInflated *) method)->declaring;
10294
10295         if (image_is_dynamic (method->klass->image)) {
10296                 MonoCustomAttrInfo *res, *ainfo;
10297                 int size;
10298
10299                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10300                 if (!aux || !aux->param_cattr)
10301                         return NULL;
10302
10303                 /* Need to copy since it will be freed later */
10304                 ainfo = aux->param_cattr [param];
10305                 if (!ainfo)
10306                         return NULL;
10307                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10308                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10309                 memcpy (res, ainfo, size);
10310                 return res;
10311         }
10312
10313         image = method->klass->image;
10314         method_index = mono_method_get_index (method);
10315         if (!method_index)
10316                 return NULL;
10317         ca = &image->tables [MONO_TABLE_METHOD];
10318
10319         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10320         if (method_index == ca->rows) {
10321                 ca = &image->tables [MONO_TABLE_PARAM];
10322                 param_last = ca->rows + 1;
10323         } else {
10324                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10325                 ca = &image->tables [MONO_TABLE_PARAM];
10326         }
10327         found = FALSE;
10328         for (i = param_list; i < param_last; ++i) {
10329                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10330                 if (param_pos == param) {
10331                         found = TRUE;
10332                         break;
10333                 }
10334         }
10335         if (!found)
10336                 return NULL;
10337         idx = i;
10338         idx <<= MONO_CUSTOM_ATTR_BITS;
10339         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10340         return mono_custom_attrs_from_index_checked (image, idx, error);
10341 }
10342
10343 gboolean
10344 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10345 {
10346         int i;
10347         MonoClass *klass;
10348         for (i = 0; i < ainfo->num_attrs; ++i) {
10349                 klass = ainfo->attrs [i].ctor->klass;
10350                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10351                         return TRUE;
10352         }
10353         return FALSE;
10354 }
10355
10356 MonoObject*
10357 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10358 {
10359         MonoError error;
10360         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10361         mono_error_assert_ok (&error); /*FIXME proper error handling*/
10362         return res;
10363 }
10364
10365 MonoObject*
10366 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10367 {
10368         int i, attr_index;
10369         MonoClass *klass;
10370         MonoArray *attrs;
10371
10372         mono_error_init (error);
10373
10374         attr_index = -1;
10375         for (i = 0; i < ainfo->num_attrs; ++i) {
10376                 klass = ainfo->attrs [i].ctor->klass;
10377                 if (mono_class_has_parent (klass, attr_klass)) {
10378                         attr_index = i;
10379                         break;
10380                 }
10381         }
10382         if (attr_index == -1)
10383                 return NULL;
10384
10385         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10386         if (!mono_error_ok (error))
10387                 return NULL;
10388         return mono_array_get (attrs, MonoObject*, attr_index);
10389 }
10390
10391 /*
10392  * mono_reflection_get_custom_attrs_info:
10393  * @obj: a reflection object handle
10394  *
10395  * Return the custom attribute info for attributes defined for the
10396  * reflection handle @obj. The objects.
10397  *
10398  * FIXME this function leaks like a sieve for SRE objects.
10399  */
10400 MonoCustomAttrInfo*
10401 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10402 {
10403         MonoError error;
10404         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10405         mono_error_assert_ok (&error);
10406         return result;
10407 }
10408
10409 /**
10410  * mono_reflection_get_custom_attrs_info_checked:
10411  * @obj: a reflection object handle
10412  * @error: set on error
10413  *
10414  * Return the custom attribute info for attributes defined for the
10415  * reflection handle @obj. The objects.
10416  *
10417  * On failure returns NULL and sets @error.
10418  *
10419  * FIXME this function leaks like a sieve for SRE objects.
10420  */
10421 MonoCustomAttrInfo*
10422 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10423 {
10424         MonoClass *klass;
10425         MonoCustomAttrInfo *cinfo = NULL;
10426         
10427         mono_error_init (error);
10428
10429         klass = obj->vtable->klass;
10430         if (klass == mono_defaults.runtimetype_class) {
10431                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10432                 return_val_if_nok (error, NULL);
10433                 klass = mono_class_from_mono_type (type);
10434                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10435                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10436                 return_val_if_nok (error, NULL);
10437         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10438                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10439                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10440                 return_val_if_nok (error, NULL);
10441         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10442                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10443                 cinfo = mono_custom_attrs_from_module (module->image, error);
10444                 return_val_if_nok (error, NULL);
10445         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10446                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10447                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10448                 return_val_if_nok (error, NULL);
10449         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10450                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10451                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10452                 return_val_if_nok (error, NULL);
10453         } else if (strcmp ("MonoField", klass->name) == 0) {
10454                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10455                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10456                 return_val_if_nok (error, NULL);
10457         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10458                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10459                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10460                 return_val_if_nok (error, NULL);
10461         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10462                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10463                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10464                 return_val_if_nok (error, NULL);
10465         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10466                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10467                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10468                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10469                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10470                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10471                         return_val_if_nok (error, NULL);
10472                 } else if (is_sr_mono_property (member_class)) {
10473                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10474                         MonoMethod *method;
10475                         if (!(method = prop->property->get))
10476                                 method = prop->property->set;
10477                         g_assert (method);
10478
10479                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10480                         return_val_if_nok (error, NULL);
10481                 } 
10482 #ifndef DISABLE_REFLECTION_EMIT
10483                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10484                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10485                         return_val_if_nok (error, NULL);
10486                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10487                         return_val_if_nok (error, NULL);
10488                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10489                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10490                         MonoMethod *method = NULL;
10491                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10492                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10493                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10494                                 method = ((MonoReflectionMethod *)c->cb)->method;
10495                         else
10496                                 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));
10497
10498                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10499                         return_val_if_nok (error, NULL);
10500                 } 
10501 #endif
10502                 else {
10503                         char *type_name = mono_type_get_full_name (member_class);
10504                         mono_error_set_not_supported (error,
10505                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10506                                                       type_name);
10507                         g_free (type_name);
10508                         return NULL;
10509                 }
10510         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10511                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10512                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10513         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10514                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10515                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10516         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10517                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10518                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10519         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10520                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10521                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10522         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10523                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10524                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10525         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10526                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10527                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10528         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10529                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10530                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10531                 return_val_if_nok (error, NULL);
10532         } else { /* handle other types here... */
10533                 g_error ("get custom attrs not yet supported for %s", klass->name);
10534         }
10535
10536         return cinfo;
10537 }
10538
10539 /*
10540  * mono_reflection_get_custom_attrs_by_type:
10541  * @obj: a reflection object handle
10542  *
10543  * Return an array with all the custom attributes defined of the
10544  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10545  * of that type are returned. The objects are fully build. Return NULL if a loading error
10546  * occurs.
10547  */
10548 MonoArray*
10549 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10550 {
10551         MonoArray *result;
10552         MonoCustomAttrInfo *cinfo;
10553
10554         mono_error_init (error);
10555
10556         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10557         return_val_if_nok (error, NULL);
10558         if (cinfo) {
10559                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10560                 if (!cinfo->cached)
10561                         mono_custom_attrs_free (cinfo);
10562                 if (!result)
10563                         return NULL;
10564         } else {
10565                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
10566         }
10567
10568         return result;
10569 }
10570
10571 /*
10572  * mono_reflection_get_custom_attrs:
10573  * @obj: a reflection object handle
10574  *
10575  * Return an array with all the custom attributes defined of the
10576  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10577  * occurs.
10578  */
10579 MonoArray*
10580 mono_reflection_get_custom_attrs (MonoObject *obj)
10581 {
10582         MonoError error;
10583
10584         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10585 }
10586
10587 /*
10588  * mono_reflection_get_custom_attrs_data:
10589  * @obj: a reflection obj handle
10590  *
10591  * Returns an array of System.Reflection.CustomAttributeData,
10592  * which include information about attributes reflected on
10593  * types loaded using the Reflection Only methods
10594  */
10595 MonoArray*
10596 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10597 {
10598         MonoError error;
10599         MonoArray* result;
10600         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10601         mono_error_cleanup (&error);
10602         return result;
10603 }
10604
10605 /*
10606  * mono_reflection_get_custom_attrs_data_checked:
10607  * @obj: a reflection obj handle
10608  * @error: set on error
10609  *
10610  * Returns an array of System.Reflection.CustomAttributeData,
10611  * which include information about attributes reflected on
10612  * types loaded using the Reflection Only methods
10613  */
10614 MonoArray*
10615 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10616 {
10617         MonoArray *result;
10618         MonoCustomAttrInfo *cinfo;
10619
10620         mono_error_init (error);
10621
10622         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10623         return_val_if_nok (error, NULL);
10624         if (cinfo) {
10625                 result = mono_custom_attrs_data_construct (cinfo, error);
10626                 if (!cinfo->cached)
10627                         mono_custom_attrs_free (cinfo);
10628                 return_val_if_nok (error, NULL);
10629         } else 
10630                 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
10631
10632         return result;
10633 }
10634
10635 static MonoReflectionType*
10636 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10637 {
10638         static MonoMethod *method_get_underlying_system_type = NULL;
10639         MonoReflectionType *rt;
10640         MonoMethod *usertype_method;
10641
10642         mono_error_init (error);
10643
10644         if (!method_get_underlying_system_type)
10645                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10646
10647         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10648
10649         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10650
10651         return rt;
10652 }
10653
10654
10655 static gboolean
10656 is_corlib_type (MonoClass *klass)
10657 {
10658         return klass->image == mono_defaults.corlib;
10659 }
10660
10661 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10662         static MonoClass *cached_class; \
10663         if (cached_class) \
10664                 return cached_class == _class; \
10665         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10666                 cached_class = _class; \
10667                 return TRUE; \
10668         } \
10669         return FALSE; \
10670 } while (0) \
10671
10672
10673 #ifndef DISABLE_REFLECTION_EMIT
10674 static gboolean
10675 is_sre_array (MonoClass *klass)
10676 {
10677         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10678 }
10679
10680 static gboolean
10681 is_sre_byref (MonoClass *klass)
10682 {
10683         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10684 }
10685
10686 static gboolean
10687 is_sre_pointer (MonoClass *klass)
10688 {
10689         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10690 }
10691
10692 static gboolean
10693 is_sre_generic_instance (MonoClass *klass)
10694 {
10695         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10696 }
10697
10698 static gboolean
10699 is_sre_type_builder (MonoClass *klass)
10700 {
10701         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10702 }
10703
10704 static gboolean
10705 is_sre_method_builder (MonoClass *klass)
10706 {
10707         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10708 }
10709
10710 static gboolean
10711 is_sre_ctor_builder (MonoClass *klass)
10712 {
10713         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10714 }
10715
10716 static gboolean
10717 is_sre_field_builder (MonoClass *klass)
10718 {
10719         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10720 }
10721
10722 static gboolean
10723 is_sre_method_on_tb_inst (MonoClass *klass)
10724 {
10725         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10726 }
10727
10728 static gboolean
10729 is_sre_ctor_on_tb_inst (MonoClass *klass)
10730 {
10731         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10732 }
10733
10734 MonoType*
10735 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10736 {
10737         MonoClass *klass;
10738         mono_error_init (error);
10739
10740         if (!ref)
10741                 return NULL;
10742         if (ref->type)
10743                 return ref->type;
10744
10745         if (is_usertype (ref)) {
10746                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10747                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10748                         return NULL;
10749                 if (ref->type)
10750                         return ref->type;
10751         }
10752
10753         klass = mono_object_class (ref);
10754
10755         if (is_sre_array (klass)) {
10756                 MonoType *res;
10757                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10758                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10759                 return_val_if_nok (error, NULL);
10760                 g_assert (base);
10761                 if (sre_array->rank == 0) //single dimentional array
10762                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10763                 else
10764                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10765                 sre_array->type.type = res;
10766                 return res;
10767         } else if (is_sre_byref (klass)) {
10768                 MonoType *res;
10769                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10770                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10771                 return_val_if_nok (error, NULL);
10772                 g_assert (base);
10773                 res = &mono_class_from_mono_type (base)->this_arg;
10774                 sre_byref->type.type = res;
10775                 return res;
10776         } else if (is_sre_pointer (klass)) {
10777                 MonoType *res;
10778                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10779                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10780                 return_val_if_nok (error, NULL);
10781                 g_assert (base);
10782                 res = &mono_ptr_class_get (base)->byval_arg;
10783                 sre_pointer->type.type = res;
10784                 return res;
10785         } else if (is_sre_generic_instance (klass)) {
10786                 MonoType *res, **types;
10787                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10788                 int i, count;
10789
10790                 count = mono_array_length (gclass->type_arguments);
10791                 types = g_new0 (MonoType*, count);
10792                 for (i = 0; i < count; ++i) {
10793                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10794                         types [i] = mono_reflection_type_get_handle (t, error);
10795                         if (!types[i] || !is_ok (error)) {
10796                                 g_free (types);
10797                                 return NULL;
10798                         }
10799                 }
10800
10801                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10802                 g_free (types);
10803                 g_assert (res);
10804                 gclass->type.type = res;
10805                 return res;
10806         }
10807
10808         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10809         return NULL;
10810 }
10811
10812 void
10813 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10814 {
10815         MonoError error;
10816         mono_reflection_type_get_handle (type, &error);
10817         mono_error_set_pending_exception (&error);
10818 }
10819
10820 static gboolean
10821 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10822 {
10823         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10824         MonoClass *klass;
10825
10826         mono_error_init (error);
10827
10828         MonoType *res = mono_reflection_type_get_handle (type, error);
10829
10830         if (!res && is_ok (error)) {
10831                 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10832         }
10833         return_val_if_nok (error, FALSE);
10834
10835         klass = mono_class_from_mono_type (res);
10836
10837         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10838         mono_domain_lock (domain);
10839
10840         if (!image_is_dynamic (klass->image)) {
10841                 mono_class_setup_supertypes (klass);
10842         } else {
10843                 if (!domain->type_hash)
10844                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10845                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10846                 mono_g_hash_table_insert (domain->type_hash, res, type);
10847         }
10848         mono_domain_unlock (domain);
10849         mono_loader_unlock ();
10850
10851         return TRUE;
10852 }
10853
10854 void
10855 mono_reflection_register_with_runtime (MonoReflectionType *type)
10856 {
10857         MonoError error;
10858         (void) reflection_register_with_runtime (type, &error);
10859         mono_error_set_pending_exception (&error);
10860 }
10861
10862 /**
10863  * LOCKING: Assumes the loader lock is held.
10864  */
10865 static MonoMethodSignature*
10866 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10867         MonoMethodSignature *sig;
10868         int count, i;
10869
10870         mono_error_init (error);
10871
10872         count = parameters? mono_array_length (parameters): 0;
10873
10874         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10875         sig->param_count = count;
10876         sig->sentinelpos = -1; /* FIXME */
10877         for (i = 0; i < count; ++i) {
10878                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10879                 if (!is_ok (error)) {
10880                         image_g_free (image, sig);
10881                         return NULL;
10882                 }
10883         }
10884         return sig;
10885 }
10886
10887 /**
10888  * LOCKING: Assumes the loader lock is held.
10889  */
10890 static MonoMethodSignature*
10891 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10892         MonoMethodSignature *sig;
10893
10894         mono_error_init (error);
10895
10896         sig = parameters_to_signature (image, ctor->parameters, error);
10897         return_val_if_nok (error, NULL);
10898         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10899         sig->ret = &mono_defaults.void_class->byval_arg;
10900         return sig;
10901 }
10902
10903 /**
10904  * LOCKING: Assumes the loader lock is held.
10905  */
10906 static MonoMethodSignature*
10907 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10908         MonoMethodSignature *sig;
10909
10910         mono_error_init (error);
10911
10912         sig = parameters_to_signature (image, method->parameters, error);
10913         return_val_if_nok (error, NULL);
10914         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10915         if (method->rtype) {
10916                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10917                 if (!is_ok (error)) {
10918                         image_g_free (image, sig);
10919                         return NULL;
10920                 }
10921         } else {
10922                 sig->ret = &mono_defaults.void_class->byval_arg;
10923         }
10924         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10925         return sig;
10926 }
10927
10928 static MonoMethodSignature*
10929 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10930         MonoMethodSignature *sig;
10931
10932         mono_error_init (error);
10933
10934         sig = parameters_to_signature (NULL, method->parameters, error);
10935         return_val_if_nok (error, NULL);
10936         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10937         if (method->rtype) {
10938                 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10939                 if (!is_ok (error)) {
10940                         g_free (sig);
10941                         return NULL;
10942                 }
10943         } else {
10944                 sig->ret = &mono_defaults.void_class->byval_arg;
10945         }
10946         sig->generic_param_count = 0;
10947         return sig;
10948 }
10949
10950 static void
10951 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10952 {
10953         mono_error_init (error);
10954         MonoClass *klass = mono_object_class (prop);
10955         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10956                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10957                 *name = mono_string_to_utf8_checked (pb->name, error);
10958                 return_if_nok (error);
10959                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10960         } else {
10961                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10962                 *name = g_strdup (p->property->name);
10963                 if (p->property->get)
10964                         *type = mono_method_signature (p->property->get)->ret;
10965                 else
10966                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10967         }
10968 }
10969
10970 static void
10971 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10972 {
10973         mono_error_init (error);
10974         MonoClass *klass = mono_object_class (field);
10975         if (strcmp (klass->name, "FieldBuilder") == 0) {
10976                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10977                 *name = mono_string_to_utf8_checked (fb->name, error);
10978                 return_if_nok (error);
10979                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10980         } else {
10981                 MonoReflectionField *f = (MonoReflectionField *)field;
10982                 *name = g_strdup (mono_field_get_name (f->field));
10983                 *type = f->field->type;
10984         }
10985 }
10986
10987 #else /* DISABLE_REFLECTION_EMIT */
10988
10989 void
10990 mono_reflection_register_with_runtime (MonoReflectionType *type)
10991 {
10992         /* This is empty */
10993 }
10994
10995 static gboolean
10996 is_sre_type_builder (MonoClass *klass)
10997 {
10998         return FALSE;
10999 }
11000
11001 static gboolean
11002 is_sre_generic_instance (MonoClass *klass)
11003 {
11004         return FALSE;
11005 }
11006
11007 static void
11008 init_type_builder_generics (MonoObject *type, MonoError *error)
11009 {
11010         mono_error_init (error);
11011 }
11012
11013 #endif /* !DISABLE_REFLECTION_EMIT */
11014
11015
11016 static gboolean
11017 is_sr_mono_field (MonoClass *klass)
11018 {
11019         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
11020 }
11021
11022 static gboolean
11023 is_sr_mono_property (MonoClass *klass)
11024 {
11025         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
11026 }
11027
11028 static gboolean
11029 is_sr_mono_method (MonoClass *klass)
11030 {
11031         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
11032 }
11033
11034 static gboolean
11035 is_sr_mono_cmethod (MonoClass *klass)
11036 {
11037         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
11038 }
11039
11040 static gboolean
11041 is_sr_mono_generic_method (MonoClass *klass)
11042 {
11043         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
11044 }
11045
11046 static gboolean
11047 is_sr_mono_generic_cmethod (MonoClass *klass)
11048 {
11049         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
11050 }
11051
11052 gboolean
11053 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
11054 {
11055         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
11056 }
11057
11058 static gboolean
11059 is_usertype (MonoReflectionType *ref)
11060 {
11061         MonoClass *klass = mono_object_class (ref);
11062         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
11063 }
11064
11065 static MonoReflectionType*
11066 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
11067 {
11068         mono_error_init (error);
11069         if (!type || type->type)
11070                 return type;
11071
11072         if (is_usertype (type)) {
11073                 type = mono_reflection_type_get_underlying_system_type (type, error);
11074                 return_val_if_nok (error, NULL);
11075                 if (is_usertype (type)) {
11076                         mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
11077                         return NULL;
11078                 }
11079         }
11080
11081         return type;
11082 }
11083 /**
11084  * encode_cattr_value:
11085  * Encode a value in a custom attribute stream of bytes.
11086  * The value to encode is either supplied as an object in argument val
11087  * (valuetypes are boxed), or as a pointer to the data in the
11088  * argument argval.
11089  * @type represents the type of the value
11090  * @buffer is the start of the buffer
11091  * @p the current position in the buffer
11092  * @buflen contains the size of the buffer and is used to return the new buffer size
11093  * if this needs to be realloced.
11094  * @retbuffer and @retp return the start and the position of the buffer
11095  * @error set on error.
11096  */
11097 static void
11098 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
11099 {
11100         MonoTypeEnum simple_type;
11101         
11102         mono_error_init (error);
11103         if ((p-buffer) + 10 >= *buflen) {
11104                 char *newbuf;
11105                 *buflen *= 2;
11106                 newbuf = (char *)g_realloc (buffer, *buflen);
11107                 p = newbuf + (p-buffer);
11108                 buffer = newbuf;
11109         }
11110         if (!argval)
11111                 argval = ((char*)arg + sizeof (MonoObject));
11112         simple_type = type->type;
11113 handle_enum:
11114         switch (simple_type) {
11115         case MONO_TYPE_BOOLEAN:
11116         case MONO_TYPE_U1:
11117         case MONO_TYPE_I1:
11118                 *p++ = *argval;
11119                 break;
11120         case MONO_TYPE_CHAR:
11121         case MONO_TYPE_U2:
11122         case MONO_TYPE_I2:
11123                 swap_with_size (p, argval, 2, 1);
11124                 p += 2;
11125                 break;
11126         case MONO_TYPE_U4:
11127         case MONO_TYPE_I4:
11128         case MONO_TYPE_R4:
11129                 swap_with_size (p, argval, 4, 1);
11130                 p += 4;
11131                 break;
11132         case MONO_TYPE_R8:
11133                 swap_with_size (p, argval, 8, 1);
11134                 p += 8;
11135                 break;
11136         case MONO_TYPE_U8:
11137         case MONO_TYPE_I8:
11138                 swap_with_size (p, argval, 8, 1);
11139                 p += 8;
11140                 break;
11141         case MONO_TYPE_VALUETYPE:
11142                 if (type->data.klass->enumtype) {
11143                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
11144                         goto handle_enum;
11145                 } else {
11146                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11147                 }
11148                 break;
11149         case MONO_TYPE_STRING: {
11150                 char *str;
11151                 guint32 slen;
11152                 if (!arg) {
11153                         *p++ = 0xFF;
11154                         break;
11155                 }
11156                 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
11157                 return_if_nok (error);
11158                 slen = strlen (str);
11159                 if ((p-buffer) + 10 + slen >= *buflen) {
11160                         char *newbuf;
11161                         *buflen *= 2;
11162                         *buflen += slen;
11163                         newbuf = (char *)g_realloc (buffer, *buflen);
11164                         p = newbuf + (p-buffer);
11165                         buffer = newbuf;
11166                 }
11167                 mono_metadata_encode_value (slen, p, &p);
11168                 memcpy (p, str, slen);
11169                 p += slen;
11170                 g_free (str);
11171                 break;
11172         }
11173         case MONO_TYPE_CLASS: {
11174                 char *str;
11175                 guint32 slen;
11176                 MonoType *arg_type;
11177                 if (!arg) {
11178                         *p++ = 0xFF;
11179                         break;
11180                 }
11181 handle_type:
11182                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11183                 return_if_nok (error);
11184
11185                 str = type_get_qualified_name (arg_type, NULL);
11186                 slen = strlen (str);
11187                 if ((p-buffer) + 10 + slen >= *buflen) {
11188                         char *newbuf;
11189                         *buflen *= 2;
11190                         *buflen += slen;
11191                         newbuf = (char *)g_realloc (buffer, *buflen);
11192                         p = newbuf + (p-buffer);
11193                         buffer = newbuf;
11194                 }
11195                 mono_metadata_encode_value (slen, p, &p);
11196                 memcpy (p, str, slen);
11197                 p += slen;
11198                 g_free (str);
11199                 break;
11200         }
11201         case MONO_TYPE_SZARRAY: {
11202                 int len, i;
11203                 MonoClass *eclass, *arg_eclass;
11204
11205                 if (!arg) {
11206                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11207                         break;
11208                 }
11209                 len = mono_array_length ((MonoArray*)arg);
11210                 *p++ = len & 0xff;
11211                 *p++ = (len >> 8) & 0xff;
11212                 *p++ = (len >> 16) & 0xff;
11213                 *p++ = (len >> 24) & 0xff;
11214                 *retp = p;
11215                 *retbuffer = buffer;
11216                 eclass = type->data.klass;
11217                 arg_eclass = mono_object_class (arg)->element_class;
11218
11219                 if (!eclass) {
11220                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11221                         eclass = mono_defaults.object_class;
11222                 }
11223                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11224                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11225                         int elsize = mono_class_array_element_size (arg_eclass);
11226                         for (i = 0; i < len; ++i) {
11227                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11228                                 return_if_nok (error);
11229                                 elptr += elsize;
11230                         }
11231                 } else if (eclass->valuetype && arg_eclass->valuetype) {
11232                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11233                         int elsize = mono_class_array_element_size (eclass);
11234                         for (i = 0; i < len; ++i) {
11235                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11236                                 return_if_nok (error);
11237                                 elptr += elsize;
11238                         }
11239                 } else {
11240                         for (i = 0; i < len; ++i) {
11241                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11242                                 return_if_nok (error);
11243                         }
11244                 }
11245                 break;
11246         }
11247         case MONO_TYPE_OBJECT: {
11248                 MonoClass *klass;
11249                 char *str;
11250                 guint32 slen;
11251
11252                 /*
11253                  * The parameter type is 'object' but the type of the actual
11254                  * argument is not. So we have to add type information to the blob
11255                  * too. This is completely undocumented in the spec.
11256                  */
11257
11258                 if (arg == NULL) {
11259                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
11260                         *p++ = 0xFF;
11261                         break;
11262                 }
11263                 
11264                 klass = mono_object_class (arg);
11265
11266                 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11267                         *p++ = 0x50;
11268                         goto handle_type;
11269                 } else {
11270                         return_if_nok (error);
11271                 }
11272
11273                 if (klass->enumtype) {
11274                         *p++ = 0x55;
11275                 } else if (klass == mono_defaults.string_class) {
11276                         simple_type = MONO_TYPE_STRING;
11277                         *p++ = 0x0E;
11278                         goto handle_enum;
11279                 } else if (klass->rank == 1) {
11280                         *p++ = 0x1D;
11281                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11282                                 /* See Partition II, Appendix B3 */
11283                                 *p++ = 0x51;
11284                         else
11285                                 *p++ = klass->element_class->byval_arg.type;
11286                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11287                         return_if_nok (error);
11288                         break;
11289                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11290                         *p++ = simple_type = klass->byval_arg.type;
11291                         goto handle_enum;
11292                 } else {
11293                         g_error ("unhandled type in custom attr");
11294                 }
11295                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11296                 slen = strlen (str);
11297                 if ((p-buffer) + 10 + slen >= *buflen) {
11298                         char *newbuf;
11299                         *buflen *= 2;
11300                         *buflen += slen;
11301                         newbuf = (char *)g_realloc (buffer, *buflen);
11302                         p = newbuf + (p-buffer);
11303                         buffer = newbuf;
11304                 }
11305                 mono_metadata_encode_value (slen, p, &p);
11306                 memcpy (p, str, slen);
11307                 p += slen;
11308                 g_free (str);
11309                 simple_type = mono_class_enum_basetype (klass)->type;
11310                 goto handle_enum;
11311         }
11312         default:
11313                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11314         }
11315         *retp = p;
11316         *retbuffer = buffer;
11317 }
11318
11319 static void
11320 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11321 {
11322         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11323                 char *str = type_get_qualified_name (type, NULL);
11324                 int slen = strlen (str);
11325
11326                 *p++ = 0x55;
11327                 /*
11328                  * This seems to be optional...
11329                  * *p++ = 0x80;
11330                  */
11331                 mono_metadata_encode_value (slen, p, &p);
11332                 memcpy (p, str, slen);
11333                 p += slen;
11334                 g_free (str);
11335         } else if (type->type == MONO_TYPE_OBJECT) {
11336                 *p++ = 0x51;
11337         } else if (type->type == MONO_TYPE_CLASS) {
11338                 /* it should be a type: encode_cattr_value () has the check */
11339                 *p++ = 0x50;
11340         } else {
11341                 mono_metadata_encode_value (type->type, p, &p);
11342                 if (type->type == MONO_TYPE_SZARRAY)
11343                         /* See the examples in Partition VI, Annex B */
11344                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11345         }
11346
11347         *retp = p;
11348 }
11349
11350 #ifndef DISABLE_REFLECTION_EMIT
11351 static void
11352 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11353 {
11354         int len;
11355
11356         mono_error_init (error);
11357
11358         /* Preallocate a large enough buffer */
11359         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11360                 char *str = type_get_qualified_name (type, NULL);
11361                 len = strlen (str);
11362                 g_free (str);
11363         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11364                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11365                 len = strlen (str);
11366                 g_free (str);
11367         } else {
11368                 len = 0;
11369         }
11370         len += strlen (name);
11371
11372         if ((p-buffer) + 20 + len >= *buflen) {
11373                 char *newbuf;
11374                 *buflen *= 2;
11375                 *buflen += len;
11376                 newbuf = (char *)g_realloc (buffer, *buflen);
11377                 p = newbuf + (p-buffer);
11378                 buffer = newbuf;
11379         }
11380
11381         encode_field_or_prop_type (type, p, &p);
11382
11383         len = strlen (name);
11384         mono_metadata_encode_value (len, p, &p);
11385         memcpy (p, name, len);
11386         p += len;
11387         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11388         return_if_nok (error);
11389         *retp = p;
11390         *retbuffer = buffer;
11391 }
11392
11393 /**
11394  * mono_reflection_get_custom_attrs_blob:
11395  * @ctor: custom attribute constructor
11396  * @ctorArgs: arguments o the constructor
11397  * @properties:
11398  * @propValues:
11399  * @fields:
11400  * @fieldValues:
11401  * 
11402  * Creates the blob of data that needs to be saved in the metadata and that represents
11403  * the custom attributed described by @ctor, @ctorArgs etc.
11404  * Returns: a Byte array representing the blob of data.
11405  */
11406 MonoArray*
11407 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11408 {
11409         MonoError error;
11410         MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11411         mono_error_cleanup (&error);
11412         return result;
11413 }
11414
11415 /**
11416  * mono_reflection_get_custom_attrs_blob_checked:
11417  * @ctor: custom attribute constructor
11418  * @ctorArgs: arguments o the constructor
11419  * @properties:
11420  * @propValues:
11421  * @fields:
11422  * @fieldValues:
11423  * @error: set on error
11424  * 
11425  * Creates the blob of data that needs to be saved in the metadata and that represents
11426  * the custom attributed described by @ctor, @ctorArgs etc.
11427  * Returns: a Byte array representing the blob of data.  On failure returns NULL and sets @error.
11428  */
11429 MonoArray*
11430 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error) 
11431 {
11432         MonoArray *result = NULL;
11433         MonoMethodSignature *sig;
11434         MonoObject *arg;
11435         char *buffer, *p;
11436         guint32 buflen, i;
11437
11438         mono_error_init (error);
11439
11440         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11441                 /* sig is freed later so allocate it in the heap */
11442                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11443                 if (!is_ok (error)) {
11444                         g_free (sig);
11445                         return NULL;
11446                 }
11447         } else {
11448                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11449         }
11450
11451         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11452         buflen = 256;
11453         p = buffer = (char *)g_malloc (buflen);
11454         /* write the prolog */
11455         *p++ = 1;
11456         *p++ = 0;
11457         for (i = 0; i < sig->param_count; ++i) {
11458                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11459                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11460                 if (!is_ok (error)) goto leave;
11461         }
11462         i = 0;
11463         if (properties)
11464                 i += mono_array_length (properties);
11465         if (fields)
11466                 i += mono_array_length (fields);
11467         *p++ = i & 0xff;
11468         *p++ = (i >> 8) & 0xff;
11469         if (properties) {
11470                 MonoObject *prop;
11471                 for (i = 0; i < mono_array_length (properties); ++i) {
11472                         MonoType *ptype;
11473                         char *pname;
11474
11475                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11476                         get_prop_name_and_type (prop, &pname, &ptype, error);
11477                         if (!is_ok (error)) goto leave;
11478                         *p++ = 0x54; /* PROPERTY signature */
11479                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11480                         g_free (pname);
11481                         if (!is_ok (error)) goto leave;
11482                 }
11483         }
11484
11485         if (fields) {
11486                 MonoObject *field;
11487                 for (i = 0; i < mono_array_length (fields); ++i) {
11488                         MonoType *ftype;
11489                         char *fname;
11490
11491                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11492                         get_field_name_and_type (field, &fname, &ftype, error);
11493                         if (!is_ok (error)) goto leave;
11494                         *p++ = 0x53; /* FIELD signature */
11495                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11496                         g_free (fname);
11497                         if (!is_ok (error)) goto leave;
11498                 }
11499         }
11500
11501         g_assert (p - buffer <= buflen);
11502         buflen = p - buffer;
11503         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
11504         if (!is_ok (error))
11505                 goto leave;
11506         p = mono_array_addr (result, char, 0);
11507         memcpy (p, buffer, buflen);
11508 leave:
11509         g_free (buffer);
11510         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11511                 g_free (sig);
11512         return result;
11513 }
11514
11515 /**
11516  * reflection_setup_internal_class:
11517  * @tb: a TypeBuilder object
11518  * @error: set on error
11519  *
11520  * Creates a MonoClass that represents the TypeBuilder.
11521  * This is a trick that lets us simplify a lot of reflection code
11522  * (and will allow us to support Build and Run assemblies easier).
11523  *
11524  * Returns TRUE on success. On failure, returns FALSE and sets @error.
11525  */
11526 static gboolean
11527 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11528 {
11529         MonoClass *klass, *parent;
11530
11531         mono_error_init (error);
11532         RESOLVE_TYPE (tb->parent, error);
11533         return_val_if_nok (error, FALSE);
11534
11535         mono_loader_lock ();
11536
11537         if (tb->parent) {
11538                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11539                 if (!is_ok (error)) {
11540                         mono_loader_unlock ();
11541                         return FALSE;
11542                 }
11543                 /* check so we can compile corlib correctly */
11544                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11545                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11546                         parent = parent_type->data.klass;
11547                 } else {
11548                         parent = mono_class_from_mono_type (parent_type);
11549                 }
11550         } else {
11551                 parent = NULL;
11552         }
11553         
11554         /* the type has already being created: it means we just have to change the parent */
11555         if (tb->type.type) {
11556                 klass = mono_class_from_mono_type (tb->type.type);
11557                 klass->parent = NULL;
11558                 /* fool mono_class_setup_parent */
11559                 klass->supertypes = NULL;
11560                 mono_class_setup_parent (klass, parent);
11561                 mono_class_setup_mono_type (klass);
11562                 mono_loader_unlock ();
11563                 return TRUE;
11564         }
11565
11566         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11567
11568         klass->image = &tb->module->dynamic_image->image;
11569
11570         klass->inited = 1; /* we lie to the runtime */
11571         klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11572         if (!is_ok (error))
11573                 goto failure;
11574         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11575         if (!is_ok (error))
11576                 goto failure;
11577         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11578         klass->flags = tb->attrs;
11579         
11580         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11581
11582         klass->element_class = klass;
11583
11584         if (mono_class_get_ref_info (klass) == NULL) {
11585
11586                 mono_class_set_ref_info (klass, tb);
11587
11588                 /* Put into cache so mono_class_get_checked () will find it.
11589                 Skip nested types as those should not be available on the global scope. */
11590                 if (!tb->nesting_type)
11591                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11592
11593                 /*
11594                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11595                 by performing a mono_class_get which does the full resolution.
11596
11597                 Working around this semantics would require us to write a lot of code for no clear advantage.
11598                 */
11599                 mono_image_append_class_to_reflection_info_set (klass);
11600         } else {
11601                 g_assert (mono_class_get_ref_info (klass) == tb);
11602         }
11603
11604         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11605
11606         if (parent != NULL) {
11607                 mono_class_setup_parent (klass, parent);
11608         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11609                 const char *old_n = klass->name;
11610                 /* trick to get relative numbering right when compiling corlib */
11611                 klass->name = "BuildingObject";
11612                 mono_class_setup_parent (klass, mono_defaults.object_class);
11613                 klass->name = old_n;
11614         }
11615
11616         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11617                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11618                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11619                 klass->instance_size = sizeof (MonoObject);
11620                 klass->size_inited = 1;
11621                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11622         }
11623
11624         mono_class_setup_mono_type (klass);
11625
11626         mono_class_setup_supertypes (klass);
11627
11628         /*
11629          * FIXME: handle interfaces.
11630          */
11631
11632         tb->type.type = &klass->byval_arg;
11633
11634         if (tb->nesting_type) {
11635                 g_assert (tb->nesting_type->type);
11636                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11637                 if (!is_ok (error)) goto failure;
11638                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11639         }
11640
11641         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11642
11643         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11644         
11645         mono_loader_unlock ();
11646         return TRUE;
11647
11648 failure:
11649         mono_loader_unlock ();
11650         return FALSE;
11651 }
11652
11653 /**
11654  * mono_reflection_setup_internal_class:
11655  * @tb: a TypeBuilder object
11656  *
11657  * (icall)
11658  * Creates a MonoClass that represents the TypeBuilder.
11659  * This is a trick that lets us simplify a lot of reflection code
11660  * (and will allow us to support Build and Run assemblies easier).
11661  *
11662  */
11663 void
11664 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11665 {
11666         MonoError error;
11667         (void) reflection_setup_internal_class (tb, &error);
11668         mono_error_set_pending_exception (&error);
11669 }
11670
11671 /*
11672  * mono_reflection_setup_generic_class:
11673  * @tb: a TypeBuilder object
11674  *
11675  * Setup the generic class before adding the first generic parameter.
11676  */
11677 void
11678 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11679 {
11680 }
11681
11682 /**
11683  * mono_reflection_create_generic_class:
11684  * @tb: a TypeBuilder object
11685  * @error: set on error
11686  *
11687  * Creates the generic class after all generic parameters have been added.
11688  * On success returns TRUE, on failure returns FALSE and sets @error.
11689  * 
11690  */
11691 gboolean
11692 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11693 {
11694
11695         MonoClass *klass;
11696         int count, i;
11697
11698         mono_error_init (error);
11699
11700         klass = mono_class_from_mono_type (tb->type.type);
11701
11702         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11703
11704         if (klass->generic_container || (count == 0))
11705                 return TRUE;
11706
11707         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11708
11709         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11710
11711         klass->generic_container->owner.klass = klass;
11712         klass->generic_container->type_argc = count;
11713         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11714
11715         klass->is_generic = 1;
11716
11717         for (i = 0; i < count; i++) {
11718                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11719                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
11720                 return_val_if_nok (error, FALSE);
11721                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11722                 klass->generic_container->type_params [i] = *param;
11723                 /*Make sure we are a diferent type instance */
11724                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11725                 klass->generic_container->type_params [i].info.pklass = NULL;
11726                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11727
11728                 g_assert (klass->generic_container->type_params [i].param.owner);
11729         }
11730
11731         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11732         return TRUE;
11733 }
11734
11735 /**
11736  * reflection_create_internal_class:
11737  * @tb: a TypeBuilder object
11738  * @error: set on error
11739  *
11740  * Actually create the MonoClass that is associated with the TypeBuilder.
11741  * On success returns TRUE, on failure returns FALSE and sets @error.
11742  *
11743  */
11744 static gboolean
11745 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11746 {
11747
11748         MonoClass *klass;
11749
11750         mono_error_init (error);
11751         klass = mono_class_from_mono_type (tb->type.type);
11752
11753         mono_loader_lock ();
11754         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11755                 MonoReflectionFieldBuilder *fb;
11756                 MonoClass *ec;
11757                 MonoType *enum_basetype;
11758
11759                 g_assert (tb->fields != NULL);
11760                 g_assert (mono_array_length (tb->fields) >= 1);
11761
11762                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11763
11764                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11765                 if (!is_ok (error)) {
11766                         mono_loader_unlock ();
11767                         return FALSE;
11768                 }
11769                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11770                         mono_loader_unlock ();
11771                         return TRUE;
11772                 }
11773
11774                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11775                 if (!is_ok (error)) {
11776                         mono_loader_unlock ();
11777                         return FALSE;
11778                 }
11779                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11780                 if (!klass->element_class)
11781                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11782
11783                 /*
11784                  * get the element_class from the current corlib.
11785                  */
11786                 ec = default_class_from_mono_type (enum_basetype);
11787                 klass->instance_size = ec->instance_size;
11788                 klass->size_inited = 1;
11789                 /* 
11790                  * this is almost safe to do with enums and it's needed to be able
11791                  * to create objects of the enum type (for use in SetConstant).
11792                  */
11793                 /* FIXME: Does this mean enums can't have method overrides ? */
11794                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11795         }
11796         mono_loader_unlock ();
11797         return TRUE;
11798 }
11799
11800 /**
11801  * mono_reflection_create_internal_class:
11802  * @tb: a TypeBuilder object
11803  *
11804  * (icall)
11805  * Actually create the MonoClass that is associated with the TypeBuilder.
11806  */
11807 void
11808 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11809 {
11810         MonoError error;
11811         (void) reflection_create_internal_class (tb, &error);
11812         mono_error_set_pending_exception (&error);
11813 }
11814
11815 static MonoMarshalSpec*
11816 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11817                                 MonoReflectionMarshal *minfo, MonoError *error)
11818 {
11819         MonoMarshalSpec *res;
11820
11821         mono_error_init (error);
11822
11823         res = image_g_new0 (image, MonoMarshalSpec, 1);
11824         res->native = (MonoMarshalNative)minfo->type;
11825
11826         switch (minfo->type) {
11827         case MONO_NATIVE_LPARRAY:
11828                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11829                 if (minfo->has_size) {
11830                         res->data.array_data.param_num = minfo->param_num;
11831                         res->data.array_data.num_elem = minfo->count;
11832                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11833                 }
11834                 else {
11835                         res->data.array_data.param_num = -1;
11836                         res->data.array_data.num_elem = -1;
11837                         res->data.array_data.elem_mult = -1;
11838                 }
11839                 break;
11840
11841         case MONO_NATIVE_BYVALTSTR:
11842         case MONO_NATIVE_BYVALARRAY:
11843                 res->data.array_data.num_elem = minfo->count;
11844                 break;
11845
11846         case MONO_NATIVE_CUSTOM:
11847                 if (minfo->marshaltyperef) {
11848                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11849                         if (!is_ok (error)) {
11850                                 image_g_free (image, res);
11851                                 return NULL;
11852                         }
11853                         res->data.custom_data.custom_name =
11854                                 type_get_fully_qualified_name (marshaltyperef);
11855                 }
11856                 if (minfo->mcookie) {
11857                         res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
11858                         if (!is_ok (error)) {
11859                                 image_g_free (image, res);
11860                                 return NULL;
11861                         }
11862                 }
11863                 break;
11864
11865         default:
11866                 break;
11867         }
11868
11869         return res;
11870 }
11871 #endif /* !DISABLE_REFLECTION_EMIT */
11872
11873 MonoReflectionMarshalAsAttribute*
11874 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11875                                                         MonoMarshalSpec *spec, MonoError *error)
11876 {
11877         MonoReflectionType *rt;
11878         MonoReflectionMarshalAsAttribute *minfo;
11879         MonoType *mtype;
11880
11881         mono_error_init (error);
11882         
11883         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11884         if (!minfo)
11885                 return NULL;
11886         minfo->utype = spec->native;
11887
11888         switch (minfo->utype) {
11889         case MONO_NATIVE_LPARRAY:
11890                 minfo->array_subtype = spec->data.array_data.elem_type;
11891                 minfo->size_const = spec->data.array_data.num_elem;
11892                 if (spec->data.array_data.param_num != -1)
11893                         minfo->size_param_index = spec->data.array_data.param_num;
11894                 break;
11895
11896         case MONO_NATIVE_BYVALTSTR:
11897         case MONO_NATIVE_BYVALARRAY:
11898                 minfo->size_const = spec->data.array_data.num_elem;
11899                 break;
11900
11901         case MONO_NATIVE_CUSTOM:
11902                 if (spec->data.custom_data.custom_name) {
11903                         mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11904                         return_val_if_nok  (error, NULL);
11905
11906                         if (mtype) {
11907                                 rt = mono_type_get_object_checked (domain, mtype, error);
11908                                 if (!rt)
11909                                         return NULL;
11910
11911                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11912                         }
11913
11914                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11915                 }
11916                 if (spec->data.custom_data.cookie)
11917                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11918                 break;
11919
11920         default:
11921                 break;
11922         }
11923
11924         return minfo;
11925 }
11926
11927 #ifndef DISABLE_REFLECTION_EMIT
11928 static MonoMethod*
11929 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11930                                          ReflectionMethodBuilder *rmb,
11931                                          MonoMethodSignature *sig,
11932                                          MonoError *error)
11933 {
11934         MonoMethod *m;
11935         MonoMethodWrapper *wrapperm;
11936         MonoMarshalSpec **specs;
11937         MonoReflectionMethodAux *method_aux;
11938         MonoImage *image;
11939         gboolean dynamic;
11940         int i;
11941
11942         mono_error_init (error);
11943         /*
11944          * Methods created using a MethodBuilder should have their memory allocated
11945          * inside the image mempool, while dynamic methods should have their memory
11946          * malloc'd.
11947          */
11948         dynamic = rmb->refs != NULL;
11949         image = dynamic ? NULL : klass->image;
11950
11951         if (!dynamic)
11952                 g_assert (!klass->generic_class);
11953
11954         mono_loader_lock ();
11955
11956         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11957                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11958                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11959         else
11960                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11961
11962         wrapperm = (MonoMethodWrapper*)m;
11963
11964         m->dynamic = dynamic;
11965         m->slot = -1;
11966         m->flags = rmb->attrs;
11967         m->iflags = rmb->iattrs;
11968         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11969         m->klass = klass;
11970         m->signature = sig;
11971         m->sre_method = TRUE;
11972         m->skip_visibility = rmb->skip_visibility;
11973         if (rmb->table_idx)
11974                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11975
11976         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11977                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11978                         m->string_ctor = 1;
11979
11980                 m->signature->pinvoke = 1;
11981         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11982                 m->signature->pinvoke = 1;
11983
11984                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11985
11986                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
11987                 mono_error_assert_ok (error);
11988                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
11989                 mono_error_assert_ok (error);
11990                 
11991                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11992
11993                 if (image_is_dynamic (klass->image))
11994                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11995
11996                 mono_loader_unlock ();
11997
11998                 return m;
11999         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
12000                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
12001                 MonoMethodHeader *header;
12002                 guint32 code_size;
12003                 gint32 max_stack, i;
12004                 gint32 num_locals = 0;
12005                 gint32 num_clauses = 0;
12006                 guint8 *code;
12007
12008                 if (rmb->ilgen) {
12009                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
12010                         code_size = rmb->ilgen->code_len;
12011                         max_stack = rmb->ilgen->max_stack;
12012                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
12013                         if (rmb->ilgen->ex_handlers)
12014                                 num_clauses = method_count_clauses (rmb->ilgen);
12015                 } else {
12016                         if (rmb->code) {
12017                                 code = mono_array_addr (rmb->code, guint8, 0);
12018                                 code_size = mono_array_length (rmb->code);
12019                                 /* we probably need to run a verifier on the code... */
12020                                 max_stack = 8; 
12021                         }
12022                         else {
12023                                 code = NULL;
12024                                 code_size = 0;
12025                                 max_stack = 8;
12026                         }
12027                 }
12028
12029                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
12030                 header->code_size = code_size;
12031                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
12032                 memcpy ((char*)header->code, code, code_size);
12033                 header->max_stack = max_stack;
12034                 header->init_locals = rmb->init_locals;
12035                 header->num_locals = num_locals;
12036
12037                 for (i = 0; i < num_locals; ++i) {
12038                         MonoReflectionLocalBuilder *lb = 
12039                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
12040
12041                         header->locals [i] = image_g_new0 (image, MonoType, 1);
12042                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
12043                         mono_error_assert_ok (error);
12044                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
12045                 }
12046
12047                 header->num_clauses = num_clauses;
12048                 if (num_clauses) {
12049                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
12050                                                                  rmb->ilgen, num_clauses, error);
12051                         mono_error_assert_ok (error);
12052                 }
12053
12054                 wrapperm->header = header;
12055         }
12056
12057         if (rmb->generic_params) {
12058                 int count = mono_array_length (rmb->generic_params);
12059                 MonoGenericContainer *container = rmb->generic_container;
12060
12061                 g_assert (container);
12062
12063                 container->type_argc = count;
12064                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
12065                 container->owner.method = m;
12066                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
12067
12068                 m->is_generic = TRUE;
12069                 mono_method_set_generic_container (m, container);
12070
12071                 for (i = 0; i < count; i++) {
12072                         MonoReflectionGenericParam *gp =
12073                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
12074                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
12075                         mono_error_assert_ok (error);
12076                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
12077                         container->type_params [i] = *param;
12078                 }
12079
12080                 /*
12081                  * The method signature might have pointers to generic parameters that belong to other methods.
12082                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
12083                  * generic parameters.
12084                  */
12085                 for (i = 0; i < m->signature->param_count; ++i) {
12086                         MonoType *t = m->signature->params [i];
12087                         if (t->type == MONO_TYPE_MVAR) {
12088                                 MonoGenericParam *gparam =  t->data.generic_param;
12089                                 if (gparam->num < count) {
12090                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
12091                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
12092                                 }
12093
12094                         }
12095                 }
12096
12097                 if (klass->generic_container) {
12098                         container->parent = klass->generic_container;
12099                         container->context.class_inst = klass->generic_container->context.class_inst;
12100                 }
12101                 container->context.method_inst = mono_get_shared_generic_inst (container);
12102         }
12103
12104         if (rmb->refs) {
12105                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
12106                 int i;
12107                 void **data;
12108
12109                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
12110
12111                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
12112                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
12113                 for (i = 0; i < rmb->nrefs; ++i)
12114                         data [i + 1] = rmb->refs [i];
12115         }
12116
12117         method_aux = NULL;
12118
12119         /* Parameter info */
12120         if (rmb->pinfo) {
12121                 if (!method_aux)
12122                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12123                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
12124                 for (i = 0; i <= m->signature->param_count; ++i) {
12125                         MonoReflectionParamBuilder *pb;
12126                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12127                                 if ((i > 0) && (pb->attrs)) {
12128                                         /* Make a copy since it might point to a shared type structure */
12129                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
12130                                         m->signature->params [i - 1]->attrs = pb->attrs;
12131                                 }
12132
12133                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
12134                                         MonoDynamicImage *assembly;
12135                                         guint32 idx, len;
12136                                         MonoTypeEnum def_type;
12137                                         char *p;
12138                                         const char *p2;
12139
12140                                         if (!method_aux->param_defaults) {
12141                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12142                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12143                                         }
12144                                         assembly = (MonoDynamicImage*)klass->image;
12145                                         idx = encode_constant (assembly, pb->def_value, &def_type);
12146                                         /* Copy the data from the blob since it might get realloc-ed */
12147                                         p = assembly->blob.data + idx;
12148                                         len = mono_metadata_decode_blob_size (p, &p2);
12149                                         len += p2 - p;
12150                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12151                                         method_aux->param_default_types [i] = def_type;
12152                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12153                                 }
12154
12155                                 if (pb->name) {
12156                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
12157                                         mono_error_assert_ok (error);
12158                                 }
12159                                 if (pb->cattrs) {
12160                                         if (!method_aux->param_cattr)
12161                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12162                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12163                                 }
12164                         }
12165                 }
12166         }
12167
12168         /* Parameter marshalling */
12169         specs = NULL;
12170         if (rmb->pinfo)         
12171                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12172                         MonoReflectionParamBuilder *pb;
12173                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12174                                 if (pb->marshal_info) {
12175                                         if (specs == NULL)
12176                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12177                                         specs [pb->position] = 
12178                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
12179                                         if (!is_ok (error)) {
12180                                                 mono_loader_unlock ();
12181                                                 image_g_free (image, specs);
12182                                                 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
12183                                                 return NULL;
12184                                         }
12185                                 }
12186                         }
12187                 }
12188         if (specs != NULL) {
12189                 if (!method_aux)
12190                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12191                 method_aux->param_marshall = specs;
12192         }
12193
12194         if (image_is_dynamic (klass->image) && method_aux)
12195                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12196
12197         mono_loader_unlock ();
12198
12199         return m;
12200 }       
12201
12202 static MonoMethod*
12203 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12204 {
12205         ReflectionMethodBuilder rmb;
12206         MonoMethodSignature *sig;
12207
12208         mono_loader_lock ();
12209         g_assert (klass->image != NULL);
12210         sig = ctor_builder_to_signature (klass->image, mb, error);
12211         mono_loader_unlock ();
12212         return_val_if_nok (error, NULL);
12213
12214         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12215                 return NULL;
12216
12217         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12218         return_val_if_nok (error, NULL);
12219         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12220
12221         /* If we are in a generic class, we might be called multiple times from inflate_method */
12222         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12223                 /* ilgen is no longer needed */
12224                 mb->ilgen = NULL;
12225         }
12226
12227         return mb->mhandle;
12228 }
12229
12230 static MonoMethod*
12231 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12232 {
12233         ReflectionMethodBuilder rmb;
12234         MonoMethodSignature *sig;
12235
12236         mono_error_init (error);
12237
12238         mono_loader_lock ();
12239         g_assert (klass->image != NULL);
12240         sig = method_builder_to_signature (klass->image, mb, error);
12241         mono_loader_unlock ();
12242         return_val_if_nok (error, NULL);
12243
12244         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12245                 return NULL;
12246
12247         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12248         return_val_if_nok (error, NULL);
12249         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12250
12251         /* If we are in a generic class, we might be called multiple times from inflate_method */
12252         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12253                 /* ilgen is no longer needed */
12254                 mb->ilgen = NULL;
12255         }
12256         return mb->mhandle;
12257 }
12258
12259 static MonoClassField*
12260 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12261 {
12262         MonoClassField *field;
12263         MonoType *custom;
12264
12265         mono_error_init (error);
12266
12267         field = g_new0 (MonoClassField, 1);
12268
12269         field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12270         mono_error_assert_ok (error);
12271         if (fb->attrs || fb->modreq || fb->modopt) {
12272                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12273                 if (!is_ok (error)) {
12274                         g_free (field);
12275                         return NULL;
12276                 }
12277                 field->type = mono_metadata_type_dup (NULL, type);
12278                 field->type->attrs = fb->attrs;
12279
12280                 g_assert (image_is_dynamic (klass->image));
12281                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12282                 g_free (field->type);
12283                 if (!is_ok (error)) {
12284                         g_free (field);
12285                         return NULL;
12286                 }
12287                 field->type = mono_metadata_type_dup (klass->image, custom);
12288                 g_free (custom);
12289         } else {
12290                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12291                 if (!is_ok (error)) {
12292                         g_free (field);
12293                         return NULL;
12294                 }
12295         }
12296         if (fb->offset != -1)
12297                 field->offset = fb->offset;
12298         field->parent = klass;
12299         mono_save_custom_attrs (klass->image, field, fb->cattrs);
12300
12301         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12302
12303         return field;
12304 }
12305 #endif
12306
12307 /**
12308  * mono_reflection_bind_generic_parameters:
12309  * @type: a managed type object (which should be some kind of generic (instance? definition?))
12310  * @type_args: the number of type arguments to bind
12311  * @types: array of type arguments
12312  * @error: set on error
12313  *
12314  * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12315  * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
12316  */
12317 MonoType*
12318 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12319 {
12320         MonoClass *klass;
12321         MonoReflectionTypeBuilder *tb = NULL;
12322         gboolean is_dynamic = FALSE;
12323         MonoClass *geninst;
12324
12325         mono_error_init (error);
12326         
12327         mono_loader_lock ();
12328
12329         if (is_sre_type_builder (mono_object_class (type))) {
12330                 tb = (MonoReflectionTypeBuilder *) type;
12331
12332                 is_dynamic = TRUE;
12333         } else if (is_sre_generic_instance (mono_object_class (type))) {
12334                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12335                 MonoReflectionType *gtd = rgi->generic_type;
12336
12337                 if (is_sre_type_builder (mono_object_class (gtd))) {
12338                         tb = (MonoReflectionTypeBuilder *)gtd;
12339                         is_dynamic = TRUE;
12340                 }
12341         }
12342
12343         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12344         if (tb && tb->generic_container) {
12345                 if (!mono_reflection_create_generic_class (tb, error)) {
12346                         mono_loader_unlock ();
12347                         return NULL;
12348                 }
12349         }
12350
12351         MonoType *t = mono_reflection_type_get_handle (type, error);
12352         if (!is_ok (error)) {
12353                 mono_loader_unlock ();
12354                 return NULL;
12355         }
12356
12357         klass = mono_class_from_mono_type (t);
12358         if (!klass->generic_container) {
12359                 mono_loader_unlock ();
12360                 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12361                 return NULL;
12362         }
12363
12364         if (klass->wastypebuilder) {
12365                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12366
12367                 is_dynamic = TRUE;
12368         }
12369
12370         mono_loader_unlock ();
12371
12372         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12373
12374         return &geninst->byval_arg;
12375 }
12376
12377 MonoClass*
12378 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12379 {
12380         MonoGenericClass *gclass;
12381         MonoGenericInst *inst;
12382
12383         g_assert (klass->generic_container);
12384
12385         inst = mono_metadata_get_generic_inst (type_argc, types);
12386         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12387
12388         return mono_generic_class_get_class (gclass);
12389 }
12390
12391 static MonoReflectionMethod*
12392 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
12393 {
12394         MonoClass *klass;
12395         MonoMethod *method, *inflated;
12396         MonoMethodInflated *imethod;
12397         MonoGenericContext tmp_context;
12398         MonoGenericInst *ginst;
12399         MonoType **type_argv;
12400         int count, i;
12401
12402         mono_error_init (error);
12403
12404         /*FIXME but this no longer should happen*/
12405         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12406 #ifndef DISABLE_REFLECTION_EMIT
12407                 MonoReflectionMethodBuilder *mb = NULL;
12408                 MonoType *tb;
12409                 MonoClass *klass;
12410
12411                 mb = (MonoReflectionMethodBuilder *) rmethod;
12412                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
12413                 return_val_if_nok (error, NULL);
12414                 klass = mono_class_from_mono_type (tb);
12415
12416                 method = methodbuilder_to_mono_method (klass, mb, error);
12417                 return_val_if_nok (error, NULL);
12418 #else
12419                 g_assert_not_reached ();
12420                 method = NULL;
12421 #endif
12422         } else {
12423                 method = rmethod->method;
12424         }
12425
12426         klass = method->klass;
12427
12428         if (method->is_inflated)
12429                 method = ((MonoMethodInflated *) method)->declaring;
12430
12431         count = mono_method_signature (method)->generic_param_count;
12432         if (count != mono_array_length (types))
12433                 return NULL;
12434
12435         type_argv = g_new0 (MonoType *, count);
12436         for (i = 0; i < count; i++) {
12437                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12438                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
12439                 if (!is_ok (error)) {
12440                         g_free (type_argv);
12441                         return NULL;
12442                 }
12443         }
12444         ginst = mono_metadata_get_generic_inst (count, type_argv);
12445         g_free (type_argv);
12446
12447         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12448         tmp_context.method_inst = ginst;
12449
12450         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
12451         mono_error_assert_ok (error);
12452         imethod = (MonoMethodInflated *) inflated;
12453
12454         /*FIXME but I think this is no longer necessary*/
12455         if (image_is_dynamic (method->klass->image)) {
12456                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12457                 /*
12458                  * This table maps metadata structures representing inflated methods/fields
12459                  * to the reflection objects representing their generic definitions.
12460                  */
12461                 mono_image_lock ((MonoImage*)image);
12462                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12463                 mono_image_unlock ((MonoImage*)image);
12464         }
12465
12466         if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
12467                 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
12468                 return NULL;
12469         }
12470         
12471         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
12472         return ret;
12473 }
12474
12475 MonoReflectionMethod*
12476 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12477 {
12478         MonoError error;
12479         MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
12480         mono_error_set_pending_exception (&error);
12481         return result;
12482 }
12483
12484
12485 #ifndef DISABLE_REFLECTION_EMIT
12486
12487 static MonoMethod *
12488 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12489 {
12490         MonoMethodInflated *imethod;
12491         MonoGenericContext *context;
12492         int i;
12493
12494         /*
12495          * With generic code sharing the klass might not be inflated.
12496          * This can happen because classes inflated with their own
12497          * type arguments are "normalized" to the uninflated class.
12498          */
12499         if (!klass->generic_class)
12500                 return method;
12501
12502         context = mono_class_get_context (klass);
12503
12504         if (klass->method.count && klass->methods) {
12505                 /* Find the already created inflated method */
12506                 for (i = 0; i < klass->method.count; ++i) {
12507                         g_assert (klass->methods [i]->is_inflated);
12508                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12509                                 break;
12510                 }
12511                 g_assert (i < klass->method.count);
12512                 imethod = (MonoMethodInflated*)klass->methods [i];
12513         } else {
12514                 MonoError error;
12515                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12516                 mono_error_assert_ok (&error);
12517         }
12518
12519         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12520                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12521
12522                 mono_image_lock ((MonoImage*)image);
12523                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12524                 mono_image_unlock ((MonoImage*)image);
12525         }
12526         return (MonoMethod *) imethod;
12527 }
12528
12529 static MonoMethod *
12530 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12531 {
12532         MonoMethod *method;
12533         MonoClass *gklass;
12534
12535         mono_error_init (error);
12536
12537         MonoClass *type_class = mono_object_class (type);
12538
12539         if (is_sre_generic_instance (type_class)) {
12540                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12541                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12542                 return_val_if_nok (error, NULL);
12543                 gklass = mono_class_from_mono_type (generic_type);
12544         } else if (is_sre_type_builder (type_class)) {
12545                 MonoType *t = mono_reflection_type_get_handle (type, error);
12546                 return_val_if_nok (error, NULL);
12547                 gklass = mono_class_from_mono_type (t);
12548         } else if (type->type) {
12549                 gklass = mono_class_from_mono_type (type->type);
12550                 gklass = mono_class_get_generic_type_definition (gklass);
12551         } else {
12552                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12553         }
12554
12555         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12556                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12557                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12558                 else {
12559                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12560                         if (!method)
12561                                 return NULL;
12562                 }
12563         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12564                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12565                 if (!method)
12566                         return NULL;
12567         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12568                 method = ((MonoReflectionMethod *) obj)->method;
12569         else {
12570                 method = NULL; /* prevent compiler warning */
12571                 g_error ("can't handle type %s", obj->vtable->klass->name);
12572         }
12573
12574         MonoType *t = mono_reflection_type_get_handle (type, error);
12575         return_val_if_nok (error, NULL);
12576         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12577 }
12578
12579 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12580 static gboolean
12581 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12582 {
12583         MonoGenericClass *gclass;
12584         MonoDynamicGenericClass *dgclass;
12585         MonoClass *klass, *gklass;
12586         MonoType *gtype;
12587         int i;
12588
12589         mono_error_init (error);
12590
12591         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12592         return_val_if_nok (error, FALSE);
12593         klass = mono_class_from_mono_type (gtype);
12594         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12595         gclass = gtype->data.generic_class;
12596
12597         if (!gclass->is_dynamic)
12598                 return TRUE;
12599
12600         dgclass = (MonoDynamicGenericClass *) gclass;
12601
12602         if (dgclass->initialized)
12603                 return TRUE;
12604
12605         gklass = gclass->container_class;
12606         mono_class_init (gklass);
12607
12608         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12609
12610         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12611         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12612         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12613
12614         for (i = 0; i < dgclass->count_fields; i++) {
12615                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12616                 MonoClassField *field, *inflated_field = NULL;
12617
12618                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12619                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12620                         return_val_if_nok (error, FALSE);
12621                 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12622                         field = ((MonoReflectionField *) obj)->field;
12623                 else {
12624                         field = NULL; /* prevent compiler warning */
12625                         g_assert_not_reached ();
12626                 }
12627
12628                 dgclass->fields [i] = *field;
12629                 dgclass->fields [i].parent = klass;
12630                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12631                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12632                 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12633                 dgclass->field_generic_types [i] = field->type;
12634                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12635                 dgclass->field_objects [i] = obj;
12636
12637                 if (inflated_field) {
12638                         g_free (inflated_field);
12639                 } else {
12640                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12641                 }
12642         }
12643
12644         dgclass->initialized = TRUE;
12645         return TRUE;
12646 }
12647
12648 void
12649 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12650 {
12651         MonoError error;
12652         (void) reflection_generic_class_initialize (type, fields, &error);
12653         mono_error_set_pending_exception (&error);
12654 }
12655
12656 void
12657 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12658 {
12659         MonoDynamicGenericClass *dgclass;
12660         int i;
12661
12662         g_assert (gclass->is_dynamic);
12663
12664         dgclass = (MonoDynamicGenericClass *)gclass;
12665
12666         for (i = 0; i < dgclass->count_fields; ++i) {
12667                 MonoClassField *field = dgclass->fields + i;
12668                 mono_metadata_free_type (field->type);
12669                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12670         }
12671 }
12672
12673 /**
12674  * fix_partial_generic_class:
12675  * @klass: a generic instantiation MonoClass
12676  * @error: set on error
12677  *
12678  * Assumes that the generic container of @klass has its vtable
12679  * initialized, and updates the parent class, insterfaces, methods and
12680  * fields of @klass by inflating the types using the generic context.
12681  *
12682  * On success returns TRUE, on failure returns FALSE and sets @error.
12683  *
12684  */
12685 static gboolean
12686 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12687 {
12688         MonoClass *gklass = klass->generic_class->container_class;
12689         MonoDynamicGenericClass *dgclass;
12690         int i;
12691
12692         mono_error_init (error);
12693
12694         if (klass->wastypebuilder)
12695                 return TRUE;
12696
12697         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12698         if (klass->parent != gklass->parent) {
12699                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12700                 if (mono_error_ok (error)) {
12701                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12702                         mono_metadata_free_type (parent_type);
12703                         if (parent != klass->parent) {
12704                                 /*fool mono_class_setup_parent*/
12705                                 klass->supertypes = NULL;
12706                                 mono_class_setup_parent (klass, parent);
12707                         }
12708                 } else {
12709                         if (gklass->wastypebuilder)
12710                                 klass->wastypebuilder = TRUE;
12711                         return FALSE;
12712                 }
12713         }
12714
12715         if (!dgclass->initialized)
12716                 return TRUE;
12717
12718         if (klass->method.count != gklass->method.count) {
12719                 klass->method.count = gklass->method.count;
12720                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12721
12722                 for (i = 0; i < klass->method.count; i++) {
12723                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12724                                 gklass->methods [i], klass, mono_class_get_context (klass), error);
12725                         mono_error_assert_ok (error);
12726                 }
12727         }
12728
12729         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12730                 klass->interface_count = gklass->interface_count;
12731                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12732                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12733
12734                 for (i = 0; i < gklass->interface_count; ++i) {
12735                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12736                         return_val_if_nok (error, FALSE);
12737
12738                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12739                         mono_metadata_free_type (iface_type);
12740
12741                         if (!ensure_runtime_vtable (klass->interfaces [i], error))
12742                                 return FALSE;
12743                 }
12744                 klass->interfaces_inited = 1;
12745         }
12746
12747         if (klass->field.count != gklass->field.count) {
12748                 klass->field.count = gklass->field.count;
12749                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12750
12751                 for (i = 0; i < klass->field.count; i++) {
12752                         klass->fields [i] = gklass->fields [i];
12753                         klass->fields [i].parent = klass;
12754                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12755                         return_val_if_nok (error, FALSE);
12756                 }
12757         }
12758
12759         /*We can only finish with this klass once it's parent has as well*/
12760         if (gklass->wastypebuilder)
12761                 klass->wastypebuilder = TRUE;
12762         return TRUE;
12763 }
12764
12765 /**
12766  * ensure_generic_class_runtime_vtable:
12767  * @klass a generic class
12768  * @error set on error
12769  *
12770  * Ensures that the generic container of @klass has a vtable and
12771  * returns TRUE on success.  On error returns FALSE and sets @error.
12772  */
12773 static gboolean
12774 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12775 {
12776         MonoClass *gklass = klass->generic_class->container_class;
12777
12778         mono_error_init (error);
12779
12780         if (!ensure_runtime_vtable (gklass, error))
12781                 return FALSE;
12782
12783         return fix_partial_generic_class (klass, error);
12784 }
12785
12786 /**
12787  * ensure_runtime_vtable:
12788  * @klass the class
12789  * @error set on error
12790  *
12791  * Ensures that @klass has a vtable and returns TRUE on success. On
12792  * error returns FALSE and sets @error.
12793  */
12794 static gboolean
12795 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12796 {
12797         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12798         int i, num, j;
12799
12800         mono_error_init (error);
12801
12802         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12803                 return TRUE;
12804         if (klass->parent)
12805                 if (!ensure_runtime_vtable (klass->parent, error))
12806                         return FALSE;
12807
12808         if (tb) {
12809                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12810                 num += tb->num_methods;
12811                 klass->method.count = num;
12812                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12813                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12814                 for (i = 0; i < num; ++i) {
12815                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12816                         if (!ctor)
12817                                 return FALSE;
12818                         klass->methods [i] = ctor;
12819                 }
12820                 num = tb->num_methods;
12821                 j = i;
12822                 for (i = 0; i < num; ++i) {
12823                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12824                         if (!meth)
12825                                 return FALSE;
12826                         klass->methods [j++] = meth;
12827                 }
12828         
12829                 if (tb->interfaces) {
12830                         klass->interface_count = mono_array_length (tb->interfaces);
12831                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12832                         for (i = 0; i < klass->interface_count; ++i) {
12833                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12834                                 return_val_if_nok (error, FALSE);
12835                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12836                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12837                                         return FALSE;
12838                         }
12839                         klass->interfaces_inited = 1;
12840                 }
12841         } else if (klass->generic_class){
12842                 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12843                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12844                         return FALSE;
12845                 }
12846         }
12847
12848         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12849                 int slot_num = 0;
12850                 for (i = 0; i < klass->method.count; ++i) {
12851                         MonoMethod *im = klass->methods [i];
12852                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12853                                 im->slot = slot_num++;
12854                 }
12855                 
12856                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12857                 mono_class_setup_interface_offsets (klass);
12858                 mono_class_setup_interface_id (klass);
12859         }
12860
12861         /*
12862          * The generic vtable is needed even if image->run is not set since some
12863          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12864          * method->slot being defined.
12865          */
12866
12867         /* 
12868          * tb->methods could not be freed since it is used for determining 
12869          * overrides during dynamic vtable construction.
12870          */
12871
12872         return TRUE;
12873 }
12874
12875 static MonoMethod*
12876 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12877 {
12878         mono_error_init (error);
12879         MonoClass *klass = mono_object_class (method);
12880         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12881                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12882                 return sr_method->method;
12883         }
12884         if (is_sre_method_builder (klass)) {
12885                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12886                 return mb->mhandle;
12887         }
12888         if (is_sre_method_on_tb_inst (klass)) {
12889                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12890                 MonoMethod *result;
12891                 /*FIXME move this to a proper method and unify with resolve_object*/
12892                 if (m->method_args) {
12893                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12894                 } else {
12895                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12896                         return_val_if_nok (error, NULL);
12897                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12898                         MonoMethod *mono_method;
12899
12900                         if (is_sre_method_builder (mono_object_class (m->mb)))
12901                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12902                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12903                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12904                         else
12905                                 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)));
12906
12907                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12908                 }
12909                 return result;
12910         }
12911
12912         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12913         return NULL;
12914 }
12915
12916 void
12917 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12918 {
12919         MonoReflectionTypeBuilder *tb;
12920         int i, j, onum;
12921         MonoReflectionMethod *m;
12922
12923         mono_error_init (error);
12924         *overrides = NULL;
12925         *num_overrides = 0;
12926
12927         g_assert (image_is_dynamic (klass->image));
12928
12929         if (!mono_class_get_ref_info (klass))
12930                 return;
12931
12932         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12933
12934         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12935
12936         onum = 0;
12937         if (tb->methods) {
12938                 for (i = 0; i < tb->num_methods; ++i) {
12939                         MonoReflectionMethodBuilder *mb = 
12940                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12941                         if (mb->override_methods)
12942                                 onum += mono_array_length (mb->override_methods);
12943                 }
12944         }
12945
12946         if (onum) {
12947                 *overrides = g_new0 (MonoMethod*, onum * 2);
12948
12949                 onum = 0;
12950                 for (i = 0; i < tb->num_methods; ++i) {
12951                         MonoReflectionMethodBuilder *mb = 
12952                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12953                         if (mb->override_methods) {
12954                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12955                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12956
12957                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12958                                         return_if_nok (error);
12959                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12960
12961                                         g_assert (mb->mhandle);
12962
12963                                         onum ++;
12964                                 }
12965                         }
12966                 }
12967         }
12968
12969         *num_overrides = onum;
12970 }
12971
12972 static void
12973 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12974 {
12975         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12976         MonoReflectionFieldBuilder *fb;
12977         MonoClassField *field;
12978         MonoImage *image = klass->image;
12979         const char *p, *p2;
12980         int i;
12981         guint32 len, idx, real_size = 0;
12982
12983         klass->field.count = tb->num_fields;
12984         klass->field.first = 0;
12985
12986         mono_error_init (error);
12987
12988         if (tb->class_size) {
12989                 if ((tb->packing_size & 0xffffff00) != 0) {
12990                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12991                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12992                         return;
12993                 }
12994                 klass->packing_size = tb->packing_size;
12995                 real_size = klass->instance_size + tb->class_size;
12996         }
12997
12998         if (!klass->field.count) {
12999                 klass->instance_size = MAX (klass->instance_size, real_size);
13000                 return;
13001         }
13002         
13003         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
13004         mono_class_alloc_ext (klass);
13005         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
13006         /*
13007         This is, guess what, a hack.
13008         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
13009         On the static path no field class is resolved, only types are built. This is the right thing to do
13010         but we suck.
13011         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
13012         */
13013         klass->size_inited = 1;
13014
13015         for (i = 0; i < klass->field.count; ++i) {
13016                 MonoArray *rva_data;
13017                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13018                 field = &klass->fields [i];
13019                 field->name = mono_string_to_utf8_image (image, fb->name, error);
13020                 if (!mono_error_ok (error))
13021                         return;
13022                 if (fb->attrs) {
13023                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
13024                         return_if_nok (error);
13025                         field->type = mono_metadata_type_dup (klass->image, type);
13026                         field->type->attrs = fb->attrs;
13027                 } else {
13028                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
13029                         return_if_nok (error);
13030                 }
13031
13032                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
13033                         char *base = mono_array_addr (rva_data, char, 0);
13034                         size_t size = mono_array_length (rva_data);
13035                         char *data = (char *)mono_image_alloc (klass->image, size);
13036                         memcpy (data, base, size);
13037                         klass->ext->field_def_values [i].data = data;
13038                 }
13039                 if (fb->offset != -1)
13040                         field->offset = fb->offset;
13041                 field->parent = klass;
13042                 fb->handle = field;
13043                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
13044
13045                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
13046                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
13047                 }
13048                 if (fb->def_value) {
13049                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13050                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
13051                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
13052                         /* Copy the data from the blob since it might get realloc-ed */
13053                         p = assembly->blob.data + idx;
13054                         len = mono_metadata_decode_blob_size (p, &p2);
13055                         len += p2 - p;
13056                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
13057                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
13058                 }
13059         }
13060
13061         klass->instance_size = MAX (klass->instance_size, real_size);
13062         mono_class_layout_fields (klass, klass->instance_size);
13063 }
13064
13065 static void
13066 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
13067 {
13068         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13069         MonoReflectionPropertyBuilder *pb;
13070         MonoImage *image = klass->image;
13071         MonoProperty *properties;
13072         int i;
13073
13074         mono_error_init (error);
13075
13076         if (!klass->ext)
13077                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13078
13079         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
13080         klass->ext->property.first = 0;
13081
13082         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
13083         klass->ext->properties = properties;
13084         for (i = 0; i < klass->ext->property.count; ++i) {
13085                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
13086                 properties [i].parent = klass;
13087                 properties [i].attrs = pb->attrs;
13088                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
13089                 if (!mono_error_ok (error))
13090                         return;
13091                 if (pb->get_method)
13092                         properties [i].get = pb->get_method->mhandle;
13093                 if (pb->set_method)
13094                         properties [i].set = pb->set_method->mhandle;
13095
13096                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
13097                 if (pb->def_value) {
13098                         guint32 len, idx;
13099                         const char *p, *p2;
13100                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
13101                         if (!klass->ext->prop_def_values)
13102                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
13103                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
13104                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
13105                         /* Copy the data from the blob since it might get realloc-ed */
13106                         p = assembly->blob.data + idx;
13107                         len = mono_metadata_decode_blob_size (p, &p2);
13108                         len += p2 - p;
13109                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
13110                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
13111                 }
13112         }
13113 }
13114
13115 static MonoReflectionEvent *
13116 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
13117 {
13118         mono_error_init (error);
13119
13120         MonoEvent *event = g_new0 (MonoEvent, 1);
13121         MonoClass *klass;
13122
13123         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13124         if (!is_ok (error)) {
13125                 g_free (event);
13126                 return NULL;
13127         }
13128         klass = mono_class_from_mono_type (type);
13129
13130         event->parent = klass;
13131         event->attrs = eb->attrs;
13132         event->name = mono_string_to_utf8_checked (eb->name, error);
13133         if (!is_ok (error)) {
13134                 g_free (event);
13135                 return NULL;
13136         }
13137         if (eb->add_method)
13138                 event->add = eb->add_method->mhandle;
13139         if (eb->remove_method)
13140                 event->remove = eb->remove_method->mhandle;
13141         if (eb->raise_method)
13142                 event->raise = eb->raise_method->mhandle;
13143
13144 #ifndef MONO_SMALL_CONFIG
13145         if (eb->other_methods) {
13146                 int j;
13147                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
13148                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13149                         MonoReflectionMethodBuilder *mb = 
13150                                 mono_array_get (eb->other_methods,
13151                                                 MonoReflectionMethodBuilder*, j);
13152                         event->other [j] = mb->mhandle;
13153                 }
13154         }
13155 #endif
13156
13157         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
13158         if (!is_ok (error)) {
13159 #ifndef MONO_SMALL_CONFIG
13160                 g_free (event->other);
13161 #endif
13162                 g_free (event);
13163                 return NULL;
13164         }
13165         return ev_obj;
13166 }
13167
13168 MonoReflectionEvent *
13169 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13170 {
13171         MonoError error;
13172         MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13173         mono_error_set_pending_exception (&error);
13174         return result;
13175 }
13176
13177 static void
13178 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13179 {
13180         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13181         MonoReflectionEventBuilder *eb;
13182         MonoImage *image = klass->image;
13183         MonoEvent *events;
13184         int i;
13185
13186         mono_error_init (error);
13187
13188         if (!klass->ext)
13189                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13190
13191         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13192         klass->ext->event.first = 0;
13193
13194         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13195         klass->ext->events = events;
13196         for (i = 0; i < klass->ext->event.count; ++i) {
13197                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13198                 events [i].parent = klass;
13199                 events [i].attrs = eb->attrs;
13200                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13201                 if (!mono_error_ok (error))
13202                         return;
13203                 if (eb->add_method)
13204                         events [i].add = eb->add_method->mhandle;
13205                 if (eb->remove_method)
13206                         events [i].remove = eb->remove_method->mhandle;
13207                 if (eb->raise_method)
13208                         events [i].raise = eb->raise_method->mhandle;
13209
13210 #ifndef MONO_SMALL_CONFIG
13211                 if (eb->other_methods) {
13212                         int j;
13213                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13214                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13215                                 MonoReflectionMethodBuilder *mb = 
13216                                         mono_array_get (eb->other_methods,
13217                                                                         MonoReflectionMethodBuilder*, j);
13218                                 events [i].other [j] = mb->mhandle;
13219                         }
13220                 }
13221 #endif
13222                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13223         }
13224 }
13225
13226 struct remove_instantiations_user_data
13227 {
13228         MonoClass *klass;
13229         MonoError *error;
13230 };
13231
13232 static gboolean
13233 remove_instantiations_of_and_ensure_contents (gpointer key,
13234                                                   gpointer value,
13235                                                   gpointer user_data)
13236 {
13237         struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13238         MonoType *type = (MonoType*)key;
13239         MonoClass *klass = data->klass;
13240         gboolean already_failed = !is_ok (data->error);
13241         MonoError lerror;
13242         MonoError *error = already_failed ? &lerror : data->error;
13243
13244         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13245                 MonoClass *inst_klass = mono_class_from_mono_type (type);
13246                 //Ensure it's safe to use it.
13247                 if (!fix_partial_generic_class (inst_klass, error)) {
13248                         mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13249                         // Marked the class with failure, but since some other instantiation already failed,
13250                         // just report that one, and swallow the error from this one.
13251                         if (already_failed)
13252                                 mono_error_cleanup (error);
13253                 }
13254                 return TRUE;
13255         } else
13256                 return FALSE;
13257 }
13258
13259 static void
13260 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13261 {
13262         mono_error_init (error);
13263         int i;
13264
13265         if (!arr)
13266                 return;
13267
13268         for (i = 0; i < mono_array_length (arr); ++i) {
13269                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13270                 if (!mono_error_ok (error))
13271                         break;
13272         }
13273 }
13274
13275 MonoReflectionType*
13276 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13277 {
13278         MonoError error;
13279         MonoClass *klass;
13280         MonoDomain* domain;
13281         MonoReflectionType* res;
13282         int i, j;
13283
13284         mono_error_init (&error);
13285
13286         domain = mono_object_domain (tb);
13287         klass = mono_class_from_mono_type (tb->type.type);
13288
13289         /*
13290          * Check for user defined Type subclasses.
13291          */
13292         RESOLVE_TYPE (tb->parent, &error);
13293         if (!is_ok (&error))
13294                 goto failure_unlocked;
13295         check_array_for_usertypes (tb->interfaces, &error);
13296         if (!is_ok (&error))
13297                 goto failure_unlocked;
13298         if (tb->fields) {
13299                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13300                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13301                         if (fb) {
13302                                 RESOLVE_TYPE (fb->type, &error);
13303                                 if (!is_ok (&error))
13304                                         goto failure_unlocked;
13305                                 check_array_for_usertypes (fb->modreq, &error);
13306                                 if (!is_ok (&error))
13307                                         goto failure_unlocked;
13308                                 check_array_for_usertypes (fb->modopt, &error);
13309                                 if (!is_ok (&error))
13310                                         goto failure_unlocked;
13311                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13312                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13313                                         if (!is_ok (&error))
13314                                                 goto failure_unlocked;
13315                                 }
13316                         }
13317                 }
13318         }
13319         if (tb->methods) {
13320                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13321                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13322                         if (mb) {
13323                                 RESOLVE_TYPE (mb->rtype, &error);
13324                                 if (!is_ok (&error))
13325                                         goto failure_unlocked;
13326                                 check_array_for_usertypes (mb->return_modreq, &error);
13327                                 if (!is_ok (&error))
13328                                         goto failure_unlocked;
13329                                 check_array_for_usertypes (mb->return_modopt, &error);
13330                                 if (!is_ok (&error))
13331                                         goto failure_unlocked;
13332                                 check_array_for_usertypes (mb->parameters, &error);
13333                                 if (!is_ok (&error))
13334                                         goto failure_unlocked;
13335                                 if (mb->param_modreq)
13336                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13337                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13338                                                 if (!is_ok (&error))
13339                                                         goto failure_unlocked;
13340                                         }
13341                                 if (mb->param_modopt)
13342                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13343                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13344                                                 if (!is_ok (&error))
13345                                                         goto failure_unlocked;
13346                                         }
13347                         }
13348                 }
13349         }
13350         if (tb->ctors) {
13351                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13352                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13353                         if (mb) {
13354                                 check_array_for_usertypes (mb->parameters, &error);
13355                                 if (!is_ok (&error))
13356                                         goto failure_unlocked;
13357                                 if (mb->param_modreq)
13358                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13359                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13360                                                 if (!is_ok (&error))
13361                                                         goto failure_unlocked;
13362                                         }
13363                                 if (mb->param_modopt)
13364                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13365                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13366                                                 if (!is_ok (&error))
13367                                                         goto failure_unlocked;
13368                                         }
13369                         }
13370                 }
13371         }
13372
13373         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13374
13375         /* 
13376          * we need to lock the domain because the lock will be taken inside
13377          * So, we need to keep the locking order correct.
13378          */
13379         mono_loader_lock ();
13380         mono_domain_lock (domain);
13381         if (klass->wastypebuilder) {
13382                 mono_domain_unlock (domain);
13383                 mono_loader_unlock ();
13384
13385                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13386                 mono_error_set_pending_exception (&error);
13387
13388                 return res;
13389         }
13390         /*
13391          * Fields to set in klass:
13392          * the various flags: delegate/unicode/contextbound etc.
13393          */
13394         klass->flags = tb->attrs;
13395         klass->has_cctor = 1;
13396
13397         mono_class_setup_parent (klass, klass->parent);
13398         /* fool mono_class_setup_supertypes */
13399         klass->supertypes = NULL;
13400         mono_class_setup_supertypes (klass);
13401         mono_class_setup_mono_type (klass);
13402
13403 #if 0
13404         if (!((MonoDynamicImage*)klass->image)->run) {
13405                 if (klass->generic_container) {
13406                         /* FIXME: The code below can't handle generic classes */
13407                         klass->wastypebuilder = TRUE;
13408                         mono_loader_unlock ();
13409                         mono_domain_unlock (domain);
13410
13411                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13412                         mono_error_set_pending_exception (&error);
13413
13414                         return res;
13415                 }
13416         }
13417 #endif
13418
13419         /* enums are done right away */
13420         if (!klass->enumtype)
13421                 if (!ensure_runtime_vtable (klass, &error))
13422                         goto failure;
13423
13424         if (tb->subtypes) {
13425                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13426                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13427                         mono_class_alloc_ext (klass);
13428                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13429                         if (!is_ok (&error)) goto failure;
13430                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13431                 }
13432         }
13433
13434         klass->nested_classes_inited = TRUE;
13435
13436         /* fields and object layout */
13437         if (klass->parent) {
13438                 if (!klass->parent->size_inited)
13439                         mono_class_init (klass->parent);
13440                 klass->instance_size = klass->parent->instance_size;
13441                 klass->sizes.class_size = 0;
13442                 klass->min_align = klass->parent->min_align;
13443                 /* if the type has no fields we won't call the field_setup
13444                  * routine which sets up klass->has_references.
13445                  */
13446                 klass->has_references |= klass->parent->has_references;
13447         } else {
13448                 klass->instance_size = sizeof (MonoObject);
13449                 klass->min_align = 1;
13450         }
13451
13452         /* FIXME: handle packing_size and instance_size */
13453         typebuilder_setup_fields (klass, &error);
13454         if (!mono_error_ok (&error))
13455                 goto failure;
13456         typebuilder_setup_properties (klass, &error);
13457         if (!mono_error_ok (&error))
13458                 goto failure;
13459
13460         typebuilder_setup_events (klass, &error);
13461         if (!mono_error_ok (&error))
13462                 goto failure;
13463
13464         klass->wastypebuilder = TRUE;
13465
13466         /* 
13467          * If we are a generic TypeBuilder, there might be instantiations in the type cache
13468          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
13469          * we want to return normal System.MonoType objects, so clear these out from the cache.
13470          *
13471          * Together with this we must ensure the contents of all instances to match the created type.
13472          */
13473         if (domain->type_hash && klass->generic_container) {
13474                 struct remove_instantiations_user_data data;
13475                 data.klass = klass;
13476                 data.error = &error;
13477                 mono_error_assert_ok (&error);
13478                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13479                 if (!is_ok (&error))
13480                         goto failure;
13481         }
13482
13483         mono_domain_unlock (domain);
13484         mono_loader_unlock ();
13485
13486         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13487                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13488                 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13489                 goto failure_unlocked;
13490         }
13491
13492         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13493         if (!is_ok (&error))
13494                 goto failure_unlocked;
13495
13496         g_assert (res != (MonoReflectionType*)tb);
13497
13498         return res;
13499
13500 failure:
13501         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13502         klass->wastypebuilder = TRUE;
13503         mono_domain_unlock (domain);
13504         mono_loader_unlock ();
13505 failure_unlocked:
13506         mono_error_set_pending_exception (&error);
13507         return NULL;
13508 }
13509
13510 static gboolean
13511 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13512 {
13513         MonoGenericParamFull *param;
13514         MonoImage *image;
13515         MonoClass *pklass;
13516
13517         mono_error_init (error);
13518
13519         image = &gparam->tbuilder->module->dynamic_image->image;
13520
13521         param = mono_image_new0 (image, MonoGenericParamFull, 1);
13522
13523         param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13524         mono_error_assert_ok (error);
13525         param->param.num = gparam->index;
13526
13527         if (gparam->mbuilder) {
13528                 if (!gparam->mbuilder->generic_container) {
13529                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13530                         return_val_if_nok (error, FALSE);
13531
13532                         MonoClass *klass = mono_class_from_mono_type (tb);
13533                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13534                         gparam->mbuilder->generic_container->is_method = TRUE;
13535                         /* 
13536                          * Cannot set owner.method, since the MonoMethod is not created yet.
13537                          * Set the image field instead, so type_in_image () works.
13538                          */
13539                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
13540                         gparam->mbuilder->generic_container->owner.image = klass->image;
13541                 }
13542                 param->param.owner = gparam->mbuilder->generic_container;
13543         } else if (gparam->tbuilder) {
13544                 if (!gparam->tbuilder->generic_container) {
13545                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13546                         return_val_if_nok (error, FALSE);
13547                         MonoClass *klass = mono_class_from_mono_type (tb);
13548                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13549                         gparam->tbuilder->generic_container->owner.klass = klass;
13550                 }
13551                 param->param.owner = gparam->tbuilder->generic_container;
13552         }
13553
13554         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13555
13556         gparam->type.type = &pklass->byval_arg;
13557
13558         mono_class_set_ref_info (pklass, gparam);
13559         mono_image_append_class_to_reflection_info_set (pklass);
13560
13561         return TRUE;
13562 }
13563
13564 void
13565 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13566 {
13567         MonoError error;
13568         (void) reflection_initialize_generic_parameter (gparam, &error);
13569         mono_error_set_pending_exception (&error);
13570 }
13571
13572
13573 static MonoArray *
13574 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
13575 {
13576         MonoReflectionModuleBuilder *module = sig->module;
13577         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13578         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13579         guint32 buflen, i;
13580         MonoArray *result;
13581         SigBuffer buf;
13582
13583         mono_error_init (error);
13584
13585         check_array_for_usertypes (sig->arguments, error);
13586         return_val_if_nok (error, NULL);
13587
13588         sigbuffer_init (&buf, 32);
13589
13590         sigbuffer_add_value (&buf, 0x07);
13591         sigbuffer_add_value (&buf, na);
13592         if (assembly != NULL){
13593                 for (i = 0; i < na; ++i) {
13594                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13595                         encode_reflection_type (assembly, type, &buf, error);
13596                         if (!is_ok (error)) goto fail;
13597                 }
13598         }
13599
13600         buflen = buf.p - buf.buf;
13601         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13602         if (!is_ok (error)) goto fail;
13603         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13604         sigbuffer_free (&buf);
13605         return result;
13606 fail:
13607         sigbuffer_free (&buf);
13608         return NULL;
13609 }
13610
13611 MonoArray *
13612 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13613 {
13614         MonoError error;
13615         MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
13616         mono_error_set_pending_exception (&error);
13617         return result;
13618 }
13619
13620 static MonoArray *
13621 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
13622 {
13623         MonoDynamicImage *assembly = sig->module->dynamic_image;
13624         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13625         guint32 buflen, i;
13626         MonoArray *result;
13627         SigBuffer buf;
13628
13629         mono_error_init (error);
13630
13631         check_array_for_usertypes (sig->arguments, error);
13632         return_val_if_nok (error, NULL);
13633
13634         sigbuffer_init (&buf, 32);
13635
13636         sigbuffer_add_value (&buf, 0x06);
13637         for (i = 0; i < na; ++i) {
13638                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13639                 encode_reflection_type (assembly, type, &buf, error);
13640                 if (!is_ok (error))
13641                         goto fail;
13642         }
13643
13644         buflen = buf.p - buf.buf;
13645         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
13646         if (!is_ok (error)) goto fail;
13647         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13648         sigbuffer_free (&buf);
13649
13650         return result;
13651 fail:
13652         sigbuffer_free (&buf);
13653         return NULL;
13654 }
13655
13656 MonoArray *
13657 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13658 {
13659         MonoError error;
13660         MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
13661         mono_error_set_pending_exception (&error);
13662         return result;
13663 }
13664
13665 typedef struct {
13666         MonoMethod *handle;
13667         MonoDomain *domain;
13668 } DynamicMethodReleaseData;
13669
13670 /*
13671  * The runtime automatically clean up those after finalization.
13672 */      
13673 static MonoReferenceQueue *dynamic_method_queue;
13674
13675 static void
13676 free_dynamic_method (void *dynamic_method)
13677 {
13678         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13679         MonoDomain *domain = data->domain;
13680         MonoMethod *method = data->handle;
13681         guint32 dis_link;
13682
13683         mono_domain_lock (domain);
13684         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13685         g_hash_table_remove (domain->method_to_dyn_method, method);
13686         mono_domain_unlock (domain);
13687         g_assert (dis_link);
13688         mono_gchandle_free (dis_link);
13689
13690         mono_runtime_free_method (domain, method);
13691         g_free (data);
13692 }
13693
13694 static gboolean
13695 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13696 {
13697         MonoReferenceQueue *queue;
13698         MonoMethod *handle;
13699         DynamicMethodReleaseData *release_data;
13700         ReflectionMethodBuilder rmb;
13701         MonoMethodSignature *sig;
13702         MonoClass *klass;
13703         MonoDomain *domain;
13704         GSList *l;
13705         int i;
13706
13707         mono_error_init (error);
13708
13709         if (mono_runtime_is_shutting_down ()) {
13710                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13711                 return FALSE;
13712         }
13713
13714         if (!(queue = dynamic_method_queue)) {
13715                 mono_loader_lock ();
13716                 if (!(queue = dynamic_method_queue))
13717                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13718                 mono_loader_unlock ();
13719         }
13720
13721         sig = dynamic_method_to_signature (mb, error);
13722         return_val_if_nok (error, FALSE);
13723
13724         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13725
13726         /*
13727          * Resolve references.
13728          */
13729         /* 
13730          * Every second entry in the refs array is reserved for storing handle_class,
13731          * which is needed by the ldtoken implementation in the JIT.
13732          */
13733         rmb.nrefs = mb->nrefs;
13734         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13735         for (i = 0; i < mb->nrefs; i += 2) {
13736                 MonoClass *handle_class;
13737                 gpointer ref;
13738                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13739
13740                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13741                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13742                         /*
13743                          * The referenced DynamicMethod should already be created by the managed
13744                          * code, except in the case of circular references. In that case, we store
13745                          * method in the refs array, and fix it up later when the referenced 
13746                          * DynamicMethod is created.
13747                          */
13748                         if (method->mhandle) {
13749                                 ref = method->mhandle;
13750                         } else {
13751                                 /* FIXME: GC object stored in unmanaged memory */
13752                                 ref = method;
13753
13754                                 /* FIXME: GC object stored in unmanaged memory */
13755                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13756                         }
13757                         handle_class = mono_defaults.methodhandle_class;
13758                 } else {
13759                         MonoException *ex = NULL;
13760                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13761                         if (!is_ok  (error)) {
13762                                 g_free (rmb.refs);
13763                                 return FALSE;
13764                         }
13765                         if (!ref)
13766                                 ex = mono_get_exception_type_load (NULL, NULL);
13767                         else if (mono_security_core_clr_enabled ())
13768                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13769
13770                         if (ex) {
13771                                 g_free (rmb.refs);
13772                                 mono_error_set_exception_instance (error, ex);
13773                                 return FALSE;
13774                         }
13775                 }
13776
13777                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13778                 rmb.refs [i + 1] = handle_class;
13779         }               
13780
13781         if (mb->owner) {
13782                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13783                 if (!is_ok (error)) {
13784                         g_free (rmb.refs);
13785                         return FALSE;
13786                 }
13787                 klass = mono_class_from_mono_type (owner_type);
13788         } else {
13789                 klass = mono_defaults.object_class;
13790         }
13791
13792         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
13793         g_free (rmb.refs);
13794         return_val_if_nok (error, FALSE);
13795
13796         release_data = g_new (DynamicMethodReleaseData, 1);
13797         release_data->handle = handle;
13798         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13799         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13800                 g_free (release_data);
13801
13802         /* Fix up refs entries pointing at us */
13803         for (l = mb->referenced_by; l; l = l->next) {
13804                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13805                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13806                 gpointer *data;
13807                 
13808                 g_assert (method->mhandle);
13809
13810                 data = (gpointer*)wrapper->method_data;
13811                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13812                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13813                                 data [i + 1] = mb->mhandle;
13814                 }
13815         }
13816         g_slist_free (mb->referenced_by);
13817
13818         /* ilgen is no longer needed */
13819         mb->ilgen = NULL;
13820
13821         domain = mono_domain_get ();
13822         mono_domain_lock (domain);
13823         if (!domain->method_to_dyn_method)
13824                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13825         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13826         mono_domain_unlock (domain);
13827
13828         return TRUE;
13829 }
13830
13831 void
13832 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13833 {
13834         MonoError error;
13835         (void) reflection_create_dynamic_method (mb, &error);
13836         mono_error_set_pending_exception (&error);
13837 }
13838
13839 #endif /* DISABLE_REFLECTION_EMIT */
13840
13841 /**
13842  * 
13843  * mono_reflection_is_valid_dynamic_token:
13844  * 
13845  * Returns TRUE if token is valid.
13846  * 
13847  */
13848 gboolean
13849 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13850 {
13851         return lookup_dyn_token (image, token) != NULL;
13852 }
13853
13854 MonoMethodSignature *
13855 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13856 {
13857         MonoMethodSignature *sig;
13858         g_assert (image_is_dynamic (image));
13859
13860         mono_error_init (error);
13861
13862         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13863         if (sig)
13864                 return sig;
13865
13866         return mono_method_signature_checked (method, error);
13867 }
13868
13869 #ifndef DISABLE_REFLECTION_EMIT
13870
13871 /**
13872  * mono_reflection_lookup_dynamic_token:
13873  *
13874  * Finish the Builder object pointed to by TOKEN and return the corresponding
13875  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13876  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13877  * mapping table.
13878  *
13879  * LOCKING: Take the loader lock
13880  */
13881 gpointer
13882 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13883 {
13884         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13885         MonoObject *obj;
13886         MonoClass *klass;
13887
13888         mono_error_init (error);
13889         
13890         obj = lookup_dyn_token (assembly, token);
13891         if (!obj) {
13892                 if (valid_token)
13893                         g_error ("Could not find required dynamic token 0x%08x", token);
13894                 else {
13895                         mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13896                         return NULL;
13897                 }
13898         }
13899
13900         if (!handle_class)
13901                 handle_class = &klass;
13902         gpointer result = resolve_object (image, obj, handle_class, context, error);
13903         return result;
13904 }
13905
13906 /*
13907  * ensure_complete_type:
13908  *
13909  *   Ensure that KLASS is completed if it is a dynamic type, or references
13910  * dynamic types.
13911  */
13912 static void
13913 ensure_complete_type (MonoClass *klass, MonoError *error)
13914 {
13915         mono_error_init (error);
13916
13917         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13918                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13919
13920                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13921                 return_if_nok (error);
13922
13923                 // Asserting here could break a lot of code
13924                 //g_assert (klass->wastypebuilder);
13925         }
13926
13927         if (klass->generic_class) {
13928                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13929                 int i;
13930
13931                 for (i = 0; i < inst->type_argc; ++i) {
13932                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13933                         return_if_nok (error);
13934                 }
13935         }
13936 }
13937
13938 static gpointer
13939 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13940 {
13941         gpointer result = NULL;
13942
13943         mono_error_init (error);
13944
13945         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13946                 result = mono_string_intern_checked ((MonoString*)obj, error);
13947                 return_val_if_nok (error, NULL);
13948                 *handle_class = mono_defaults.string_class;
13949                 g_assert (result);
13950         } else if (strcmp (obj->vtable->klass->name, "RuntimeType") == 0) {
13951                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13952                 return_val_if_nok (error, NULL);
13953                 MonoClass *mc = mono_class_from_mono_type (type);
13954                 if (!mono_class_init (mc)) {
13955                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13956                         return NULL;
13957                 }
13958
13959                 if (context) {
13960                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13961                         return_val_if_nok (error, NULL);
13962
13963                         result = mono_class_from_mono_type (inflated);
13964                         mono_metadata_free_type (inflated);
13965                 } else {
13966                         result = mono_class_from_mono_type (type);
13967                 }
13968                 *handle_class = mono_defaults.typehandle_class;
13969                 g_assert (result);
13970         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13971                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13972                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13973                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13974                 result = ((MonoReflectionMethod*)obj)->method;
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                 g_assert (result);
13981         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13982                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13983                 result = mb->mhandle;
13984                 if (!result) {
13985                         /* Type is not yet created */
13986                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13987
13988                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13989                         return_val_if_nok (error, NULL);
13990
13991                         /*
13992                          * Hopefully this has been filled in by calling CreateType() on the
13993                          * TypeBuilder.
13994                          */
13995                         /*
13996                          * TODO: This won't work if the application finishes another 
13997                          * TypeBuilder instance instead of this one.
13998                          */
13999                         result = mb->mhandle;
14000                 }
14001                 if (context) {
14002                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14003                         mono_error_assert_ok (error);
14004                 }
14005                 *handle_class = mono_defaults.methodhandle_class;
14006         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
14007                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
14008
14009                 result = cb->mhandle;
14010                 if (!result) {
14011                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
14012
14013                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14014                         return_val_if_nok (error, NULL);
14015                         result = cb->mhandle;
14016                 }
14017                 if (context) {
14018                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14019                         mono_error_assert_ok (error);
14020                 }
14021                 *handle_class = mono_defaults.methodhandle_class;
14022         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
14023                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
14024
14025                 ensure_complete_type (field->parent, error);
14026                 return_val_if_nok (error, NULL);
14027
14028                 if (context) {
14029                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
14030                         return_val_if_nok (error, NULL);
14031
14032                         MonoClass *klass = mono_class_from_mono_type (inflated);
14033                         MonoClassField *inflated_field;
14034                         gpointer iter = NULL;
14035                         mono_metadata_free_type (inflated);
14036                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
14037                                 if (!strcmp (field->name, inflated_field->name))
14038                                         break;
14039                         }
14040                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
14041                         result = inflated_field;
14042                 } else {
14043                         result = field;
14044                 }
14045                 *handle_class = mono_defaults.fieldhandle_class;
14046                 g_assert (result);
14047         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
14048                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
14049                 result = fb->handle;
14050
14051                 if (!result) {
14052                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
14053
14054                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14055                         return_val_if_nok (error, NULL);
14056                         result = fb->handle;
14057                 }
14058
14059                 if (fb->handle && fb->handle->parent->generic_container) {
14060                         MonoClass *klass = fb->handle->parent;
14061                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
14062                         return_val_if_nok (error, NULL);
14063
14064                         MonoClass *inflated = mono_class_from_mono_type (type);
14065
14066                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
14067                         g_assert (result);
14068                         mono_metadata_free_type (type);
14069                 }
14070                 *handle_class = mono_defaults.fieldhandle_class;
14071         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
14072                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
14073                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
14074                 return_val_if_nok (error, NULL);
14075                 MonoClass *klass;
14076
14077                 klass = type->data.klass;
14078                 if (klass->wastypebuilder) {
14079                         /* Already created */
14080                         result = klass;
14081                 }
14082                 else {
14083                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
14084                         return_val_if_nok (error, NULL);
14085                         result = type->data.klass;
14086                         g_assert (result);
14087                 }
14088                 *handle_class = mono_defaults.typehandle_class;
14089         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
14090                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
14091                 MonoMethodSignature *sig;
14092                 int nargs, i;
14093
14094                 if (helper->arguments)
14095                         nargs = mono_array_length (helper->arguments);
14096                 else
14097                         nargs = 0;
14098
14099                 sig = mono_metadata_signature_alloc (image, nargs);
14100                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
14101                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
14102
14103                 if (helper->unmanaged_call_conv) { /* unmanaged */
14104                         sig->call_convention = helper->unmanaged_call_conv - 1;
14105                         sig->pinvoke = TRUE;
14106                 } else if (helper->call_conv & 0x02) {
14107                         sig->call_convention = MONO_CALL_VARARG;
14108                 } else {
14109                         sig->call_convention = MONO_CALL_DEFAULT;
14110                 }
14111
14112                 sig->param_count = nargs;
14113                 /* TODO: Copy type ? */
14114                 sig->ret = helper->return_type->type;
14115                 for (i = 0; i < nargs; ++i) {
14116                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
14117                         if (!is_ok (error)) {
14118                                 image_g_free (image, sig);
14119                                 return NULL;
14120                         }
14121                 }
14122
14123                 result = sig;
14124                 *handle_class = NULL;
14125         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
14126                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
14127                 /* Already created by the managed code */
14128                 g_assert (method->mhandle);
14129                 result = method->mhandle;
14130                 *handle_class = mono_defaults.methodhandle_class;
14131         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
14132                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14133                 return_val_if_nok (error, NULL);
14134                 type = mono_class_inflate_generic_type_checked (type, context, error);
14135                 return_val_if_nok (error, NULL);
14136
14137                 result = mono_class_from_mono_type (type);
14138                 *handle_class = mono_defaults.typehandle_class;
14139                 g_assert (result);
14140                 mono_metadata_free_type (type);
14141         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
14142                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14143                 return_val_if_nok (error, NULL);
14144                 type = mono_class_inflate_generic_type_checked (type, context, error);
14145                 return_val_if_nok (error, NULL);
14146
14147                 result = mono_class_from_mono_type (type);
14148                 *handle_class = mono_defaults.typehandle_class;
14149                 g_assert (result);
14150                 mono_metadata_free_type (type);
14151         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
14152                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
14153                 MonoClass *inflated;
14154                 MonoType *type;
14155                 MonoClassField *field;
14156
14157                 if (is_sre_field_builder (mono_object_class (f->fb)))
14158                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
14159                 else if (is_sr_mono_field (mono_object_class (f->fb)))
14160                         field = ((MonoReflectionField*)f->fb)->field;
14161                 else
14162                         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)));
14163
14164                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
14165                 return_val_if_nok (error, NULL);
14166                 type = mono_class_inflate_generic_type_checked (finst, context, error);
14167                 return_val_if_nok (error, NULL);
14168
14169                 inflated = mono_class_from_mono_type (type);
14170
14171                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
14172                 ensure_complete_type (field->parent, error);
14173                 if (!is_ok (error)) {
14174                         mono_metadata_free_type (type);
14175                         return NULL;
14176                 }
14177
14178                 g_assert (result);
14179                 mono_metadata_free_type (type);
14180                 *handle_class = mono_defaults.fieldhandle_class;
14181         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
14182                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14183                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14184                 return_val_if_nok (error, NULL);
14185                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14186                 return_val_if_nok (error, NULL);
14187
14188                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14189                 MonoMethod *method;
14190
14191                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14192                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14193                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14194                         method = ((MonoReflectionMethod *)c->cb)->method;
14195                 else
14196                         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)));
14197
14198                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14199                 *handle_class = mono_defaults.methodhandle_class;
14200                 mono_metadata_free_type (type);
14201         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14202                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14203                 if (m->method_args) {
14204                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14205                         return_val_if_nok (error, NULL);
14206                         if (context) {
14207                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14208                                 mono_error_assert_ok (error);
14209                         }
14210                 } else {
14211                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14212                         return_val_if_nok (error, NULL);
14213                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14214                         return_val_if_nok (error, NULL);
14215
14216                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
14217                         MonoMethod *method;
14218
14219                         if (is_sre_method_builder (mono_object_class (m->mb)))
14220                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14221                         else if (is_sr_mono_method (mono_object_class (m->mb)))
14222                                 method = ((MonoReflectionMethod *)m->mb)->method;
14223                         else
14224                                 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)));
14225
14226                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14227                         mono_metadata_free_type (type);
14228                 }
14229                 *handle_class = mono_defaults.methodhandle_class;
14230         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14231                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14232                 MonoType *mtype;
14233                 MonoClass *klass;
14234                 MonoMethod *method;
14235                 gpointer iter;
14236                 char *name;
14237
14238                 mtype = mono_reflection_type_get_handle (m->parent, error);
14239                 return_val_if_nok (error, NULL);
14240                 klass = mono_class_from_mono_type (mtype);
14241
14242                 /* Find the method */
14243
14244                 name = mono_string_to_utf8_checked (m->name, error);
14245                 return_val_if_nok (error, NULL);
14246                 iter = NULL;
14247                 while ((method = mono_class_get_methods (klass, &iter))) {
14248                         if (!strcmp (method->name, name))
14249                                 break;
14250                 }
14251                 g_free (name);
14252
14253                 // FIXME:
14254                 g_assert (method);
14255                 // FIXME: Check parameters/return value etc. match
14256
14257                 result = method;
14258                 *handle_class = mono_defaults.methodhandle_class;
14259         } else if (is_sre_array (mono_object_get_class(obj)) ||
14260                                 is_sre_byref (mono_object_get_class(obj)) ||
14261                                 is_sre_pointer (mono_object_get_class(obj))) {
14262                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14263                 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14264                 return_val_if_nok (error, NULL);
14265
14266                 if (context) {
14267                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14268                         return_val_if_nok (error, NULL);
14269
14270                         result = mono_class_from_mono_type (inflated);
14271                         mono_metadata_free_type (inflated);
14272                 } else {
14273                         result = mono_class_from_mono_type (type);
14274                 }
14275                 *handle_class = mono_defaults.typehandle_class;
14276         } else {
14277                 g_print ("%s\n", obj->vtable->klass->name);
14278                 g_assert_not_reached ();
14279         }
14280         return result;
14281 }
14282
14283 #else /* DISABLE_REFLECTION_EMIT */
14284
14285 MonoArray*
14286 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
14287 {
14288         g_assert_not_reached ();
14289         return NULL;
14290 }
14291
14292 void
14293 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14294 {
14295         g_assert_not_reached ();
14296 }
14297
14298 void
14299 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14300 {
14301         g_assert_not_reached ();
14302 }
14303
14304 gboolean
14305 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
14306 {
14307         g_assert_not_reached ();
14308         return FALSE;
14309 }
14310
14311 void
14312 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14313 {
14314         g_assert_not_reached ();
14315 }
14316
14317 void
14318 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14319 {
14320         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14321 }
14322
14323 void
14324 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14325 {
14326         g_assert_not_reached ();
14327 }
14328
14329 void
14330 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14331 {
14332         g_assert_not_reached ();
14333 }
14334
14335 MonoReflectionModule *
14336 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14337 {
14338         g_assert_not_reached ();
14339         return NULL;
14340 }
14341
14342 guint32
14343 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14344 {
14345         g_assert_not_reached ();
14346         return 0;
14347 }
14348
14349 guint32
14350 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14351 {
14352         g_assert_not_reached ();
14353         return 0;
14354 }
14355
14356 guint32
14357 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
14358                          gboolean create_open_instance, gboolean register_token, MonoError *error)
14359 {
14360         g_assert_not_reached ();
14361         return 0;
14362 }
14363
14364 void
14365 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14366 {
14367 }
14368
14369 void
14370 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14371 {
14372         g_assert_not_reached ();
14373 }
14374
14375 void
14376 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14377 {
14378         mono_error_init (error);
14379         *overrides = NULL;
14380         *num_overrides = 0;
14381 }
14382
14383 MonoReflectionEvent *
14384 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14385 {
14386         g_assert_not_reached ();
14387         return NULL;
14388 }
14389
14390 MonoReflectionType*
14391 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14392 {
14393         g_assert_not_reached ();
14394         return NULL;
14395 }
14396
14397 void
14398 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14399 {
14400         g_assert_not_reached ();
14401 }
14402
14403 MonoArray *
14404 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14405 {
14406         g_assert_not_reached ();
14407         return NULL;
14408 }
14409
14410 MonoArray *
14411 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14412 {
14413         g_assert_not_reached ();
14414         return NULL;
14415 }
14416
14417 void 
14418 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14419 {
14420 }
14421
14422 gpointer
14423 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
14424 {
14425         mono_error_init (error);
14426         return NULL;
14427 }
14428
14429 MonoType*
14430 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14431 {
14432         mono_error_init (error);
14433         if (!ref)
14434                 return NULL;
14435         return ref->type;
14436 }
14437
14438 void
14439 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14440 {
14441         g_assert_not_reached ();
14442 }
14443
14444 #endif /* DISABLE_REFLECTION_EMIT */
14445
14446 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14447 const static guint32 declsec_flags_map[] = {
14448         0x00000000,                                     /* empty */
14449         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
14450         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
14451         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
14452         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
14453         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
14454         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
14455         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
14456         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
14457         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
14458         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
14459         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
14460         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
14461         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
14462         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
14463         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
14464         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
14465         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
14466         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
14467 };
14468
14469 /*
14470  * Returns flags that includes all available security action associated to the handle.
14471  * @token: metadata token (either for a class or a method)
14472  * @image: image where resides the metadata.
14473  */
14474 static guint32
14475 mono_declsec_get_flags (MonoImage *image, guint32 token)
14476 {
14477         int index = mono_metadata_declsec_from_index (image, token);
14478         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14479         guint32 result = 0;
14480         guint32 action;
14481         int i;
14482
14483         /* HasSecurity can be present for other, not specially encoded, attributes,
14484            e.g. SuppressUnmanagedCodeSecurityAttribute */
14485         if (index < 0)
14486                 return 0;
14487
14488         for (i = index; i < t->rows; i++) {
14489                 guint32 cols [MONO_DECL_SECURITY_SIZE];
14490
14491                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14492                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14493                         break;
14494
14495                 action = cols [MONO_DECL_SECURITY_ACTION];
14496                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14497                         result |= declsec_flags_map [action];
14498                 } else {
14499                         g_assert_not_reached ();
14500                 }
14501         }
14502         return result;
14503 }
14504
14505 /*
14506  * Get the security actions (in the form of flags) associated with the specified method.
14507  *
14508  * @method: The method for which we want the declarative security flags.
14509  * Return the declarative security flags for the method (only).
14510  *
14511  * Note: To keep MonoMethod size down we do not cache the declarative security flags
14512  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
14513  */
14514 guint32
14515 mono_declsec_flags_from_method (MonoMethod *method)
14516 {
14517         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14518                 /* FIXME: No cache (for the moment) */
14519                 guint32 idx = mono_method_get_index (method);
14520                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14521                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14522                 return mono_declsec_get_flags (method->klass->image, idx);
14523         }
14524         return 0;
14525 }
14526
14527 /*
14528  * Get the security actions (in the form of flags) associated with the specified class.
14529  *
14530  * @klass: The class for which we want the declarative security flags.
14531  * Return the declarative security flags for the class.
14532  *
14533  * Note: We cache the flags inside the MonoClass structure as this will get 
14534  *       called very often (at least for each method).
14535  */
14536 guint32
14537 mono_declsec_flags_from_class (MonoClass *klass)
14538 {
14539         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14540                 if (!klass->ext || !klass->ext->declsec_flags) {
14541                         guint32 idx;
14542
14543                         idx = mono_metadata_token_index (klass->type_token);
14544                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14545                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14546                         mono_loader_lock ();
14547                         mono_class_alloc_ext (klass);
14548                         mono_loader_unlock ();
14549                         /* we cache the flags on classes */
14550                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14551                 }
14552                 return klass->ext->declsec_flags;
14553         }
14554         return 0;
14555 }
14556
14557 /*
14558  * Get the security actions (in the form of flags) associated with the specified assembly.
14559  *
14560  * @assembly: The assembly for which we want the declarative security flags.
14561  * Return the declarative security flags for the assembly.
14562  */
14563 guint32
14564 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14565 {
14566         guint32 idx = 1; /* there is only one assembly */
14567         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14568         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14569         return mono_declsec_get_flags (assembly->image, idx);
14570 }
14571
14572
14573 /*
14574  * Fill actions for the specific index (which may either be an encoded class token or
14575  * an encoded method token) from the metadata image.
14576  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14577  */
14578 static MonoBoolean
14579 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14580         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14581 {
14582         MonoBoolean result = FALSE;
14583         MonoTableInfo *t;
14584         guint32 cols [MONO_DECL_SECURITY_SIZE];
14585         int index = mono_metadata_declsec_from_index (image, token);
14586         int i;
14587
14588         t  = &image->tables [MONO_TABLE_DECLSECURITY];
14589         for (i = index; i < t->rows; i++) {
14590                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14591
14592                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14593                         return result;
14594
14595                 /* if present only replace (class) permissions with method permissions */
14596                 /* if empty accept either class or method permissions */
14597                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14598                         if (!actions->demand.blob) {
14599                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14600                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14601                                 actions->demand.blob = (char*) (blob + 2);
14602                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14603                                 result = TRUE;
14604                         }
14605                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14606                         if (!actions->noncasdemand.blob) {
14607                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14608                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14609                                 actions->noncasdemand.blob = (char*) (blob + 2);
14610                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14611                                 result = TRUE;
14612                         }
14613                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14614                         if (!actions->demandchoice.blob) {
14615                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14616                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14617                                 actions->demandchoice.blob = (char*) (blob + 2);
14618                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14619                                 result = TRUE;
14620                         }
14621                 }
14622         }
14623
14624         return result;
14625 }
14626
14627 static MonoBoolean
14628 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14629         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14630 {
14631         guint32 idx = mono_metadata_token_index (klass->type_token);
14632         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14633         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14634         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14635 }
14636
14637 static MonoBoolean
14638 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14639         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14640 {
14641         guint32 idx = mono_method_get_index (method);
14642         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14643         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14644         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14645 }
14646
14647 /*
14648  * Collect all actions (that requires to generate code in mini) assigned for
14649  * the specified method.
14650  * Note: Don't use the content of actions if the function return FALSE.
14651  */
14652 MonoBoolean
14653 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14654 {
14655         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14656                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14657         MonoBoolean result = FALSE;
14658         guint32 flags;
14659
14660         /* quick exit if no declarative security is present in the metadata */
14661         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14662                 return FALSE;
14663
14664         /* we want the original as the wrapper is "free" of the security informations */
14665         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14666                 method = mono_marshal_method_from_wrapper (method);
14667                 if (!method)
14668                         return FALSE;
14669         }
14670
14671         /* First we look for method-level attributes */
14672         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14673                 mono_class_init (method->klass);
14674                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14675
14676                 result = mono_declsec_get_method_demands_params (method, demands, 
14677                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14678         }
14679
14680         /* Here we use (or create) the class declarative cache to look for demands */
14681         flags = mono_declsec_flags_from_class (method->klass);
14682         if (flags & mask) {
14683                 if (!result) {
14684                         mono_class_init (method->klass);
14685                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14686                 }
14687                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14688                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14689         }
14690
14691         /* The boolean return value is used as a shortcut in case nothing needs to
14692            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14693         return result;
14694 }
14695
14696
14697 /*
14698  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14699  *
14700  * Note: Don't use the content of actions if the function return FALSE.
14701  */
14702 MonoBoolean
14703 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14704 {
14705         MonoBoolean result = FALSE;
14706         guint32 flags;
14707
14708         /* quick exit if no declarative security is present in the metadata */
14709         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14710                 return FALSE;
14711
14712         /* we want the original as the wrapper is "free" of the security informations */
14713         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14714                 method = mono_marshal_method_from_wrapper (method);
14715                 if (!method)
14716                         return FALSE;
14717         }
14718
14719         /* results are independant - zeroize both */
14720         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14721         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14722
14723         /* First we look for method-level attributes */
14724         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14725                 mono_class_init (method->klass);
14726
14727                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14728                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14729         }
14730
14731         /* Here we use (or create) the class declarative cache to look for demands */
14732         flags = mono_declsec_flags_from_class (method->klass);
14733         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14734                 mono_class_init (method->klass);
14735
14736                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14737                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14738         }
14739
14740         return result;
14741 }
14742
14743 /*
14744  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14745  *
14746  * @klass       The inherited class - this is the class that provides the security check (attributes)
14747  * @demans      
14748  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14749  * 
14750  * Note: Don't use the content of actions if the function return FALSE.
14751  */
14752 MonoBoolean
14753 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14754 {
14755         MonoBoolean result = FALSE;
14756         guint32 flags;
14757
14758         /* quick exit if no declarative security is present in the metadata */
14759         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14760                 return FALSE;
14761
14762         /* Here we use (or create) the class declarative cache to look for demands */
14763         flags = mono_declsec_flags_from_class (klass);
14764         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14765                 mono_class_init (klass);
14766                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14767
14768                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14769                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14770         }
14771
14772         return result;
14773 }
14774
14775 /*
14776  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14777  *
14778  * Note: Don't use the content of actions if the function return FALSE.
14779  */
14780 MonoBoolean
14781 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14782 {
14783         /* quick exit if no declarative security is present in the metadata */
14784         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14785                 return FALSE;
14786
14787         /* we want the original as the wrapper is "free" of the security informations */
14788         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14789                 method = mono_marshal_method_from_wrapper (method);
14790                 if (!method)
14791                         return FALSE;
14792         }
14793
14794         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14795                 mono_class_init (method->klass);
14796                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14797
14798                 return mono_declsec_get_method_demands_params (method, demands, 
14799                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14800         }
14801         return FALSE;
14802 }
14803
14804
14805 static MonoBoolean
14806 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14807 {
14808         guint32 cols [MONO_DECL_SECURITY_SIZE];
14809         MonoTableInfo *t;
14810         int i;
14811
14812         int index = mono_metadata_declsec_from_index (image, token);
14813         if (index == -1)
14814                 return FALSE;
14815
14816         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14817         for (i = index; i < t->rows; i++) {
14818                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14819
14820                 /* shortcut - index are ordered */
14821                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14822                         return FALSE;
14823
14824                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14825                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14826                         entry->blob = (char*) (metadata + 2);
14827                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14828                         return TRUE;
14829                 }
14830         }
14831
14832         return FALSE;
14833 }
14834
14835 MonoBoolean
14836 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14837 {
14838         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14839                 guint32 idx = mono_method_get_index (method);
14840                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14841                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14842                 return get_declsec_action (method->klass->image, idx, action, entry);
14843         }
14844         return FALSE;
14845 }
14846
14847 MonoBoolean
14848 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14849 {
14850         /* use cache */
14851         guint32 flags = mono_declsec_flags_from_class (klass);
14852         if (declsec_flags_map [action] & flags) {
14853                 guint32 idx = mono_metadata_token_index (klass->type_token);
14854                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14855                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14856                 return get_declsec_action (klass->image, idx, action, entry);
14857         }
14858         return FALSE;
14859 }
14860
14861 MonoBoolean
14862 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14863 {
14864         guint32 idx = 1; /* there is only one assembly */
14865         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14866         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14867
14868         return get_declsec_action (assembly->image, idx, action, entry);
14869 }
14870
14871 gboolean
14872 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14873 {
14874         MonoObject *res, *exc;
14875         void *params [1];
14876         static MonoMethod *method = NULL;
14877
14878         mono_error_init (error);
14879
14880         if (method == NULL) {
14881                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14882                 g_assert (method);
14883         }
14884
14885         /* 
14886          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14887          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14888          */
14889         g_assert (mono_class_get_ref_info (klass));
14890         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14891
14892         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14893         return_val_if_nok (error, FALSE);
14894
14895         MonoError inner_error;
14896         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &inner_error);
14897
14898         if (exc || !is_ok (&inner_error)) {
14899                 mono_error_cleanup (&inner_error);
14900                 return FALSE;
14901         } else
14902                 return *(MonoBoolean*)mono_object_unbox (res);
14903 }
14904
14905 /**
14906  * mono_reflection_type_get_type:
14907  * @reftype: the System.Type object
14908  *
14909  * Returns the MonoType* associated with the C# System.Type object @reftype.
14910  */
14911 MonoType*
14912 mono_reflection_type_get_type (MonoReflectionType *reftype)
14913 {
14914         g_assert (reftype);
14915
14916         MonoError error;
14917         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14918         mono_error_assert_ok (&error);
14919         return result;
14920 }
14921
14922 /**
14923  * mono_reflection_assembly_get_assembly:
14924  * @refassembly: the System.Reflection.Assembly object
14925  *
14926  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14927  */
14928 MonoAssembly*
14929 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14930 {
14931         g_assert (refassembly);
14932
14933         return refassembly->assembly;
14934 }
14935