Merge pull request #2768 from lambdageek/dev/monoerror-cominterop
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
47
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
50
51 typedef struct {
52         char *p;
53         char *buf;
54         char *end;
55 } SigBuffer;
56
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA  0x00002000
62
63 typedef struct {
64         MonoReflectionILGen *ilgen;
65         MonoReflectionType *rtype;
66         MonoArray *parameters;
67         MonoArray *generic_params;
68         MonoGenericContainer *generic_container;
69         MonoArray *pinfo;
70         MonoArray *opt_types;
71         guint32 attrs;
72         guint32 iattrs;
73         guint32 call_conv;
74         guint32 *table_idx; /* note: it's a pointer */
75         MonoArray *code;
76         MonoObject *type;
77         MonoString *name;
78         MonoBoolean init_locals;
79         MonoBoolean skip_visibility;
80         MonoArray *return_modreq;
81         MonoArray *return_modopt;
82         MonoArray *param_modreq;
83         MonoArray *param_modopt;
84         MonoArray *permissions;
85         MonoMethod *mhandle;
86         guint32 nrefs;
87         gpointer *refs;
88         /* for PInvoke */
89         int charset, extra_flags, native_cc;
90         MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
92
93 typedef struct {
94         guint32 owner;
95         MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
97
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
99         MONO_MODULE_SIZE,
100         MONO_TYPEREF_SIZE,
101         MONO_TYPEDEF_SIZE,
102         0,
103         MONO_FIELD_SIZE,
104         0,
105         MONO_METHOD_SIZE,
106         0,
107         MONO_PARAM_SIZE,
108         MONO_INTERFACEIMPL_SIZE,
109         MONO_MEMBERREF_SIZE,    /* 0x0A */
110         MONO_CONSTANT_SIZE,
111         MONO_CUSTOM_ATTR_SIZE,
112         MONO_FIELD_MARSHAL_SIZE,
113         MONO_DECL_SECURITY_SIZE,
114         MONO_CLASS_LAYOUT_SIZE,
115         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116         MONO_STAND_ALONE_SIGNATURE_SIZE,
117         MONO_EVENT_MAP_SIZE,
118         0,
119         MONO_EVENT_SIZE,
120         MONO_PROPERTY_MAP_SIZE,
121         0,
122         MONO_PROPERTY_SIZE,
123         MONO_METHOD_SEMA_SIZE,
124         MONO_METHODIMPL_SIZE,
125         MONO_MODULEREF_SIZE,    /* 0x1A */
126         MONO_TYPESPEC_SIZE,
127         MONO_IMPLMAP_SIZE,      
128         MONO_FIELD_RVA_SIZE,
129         0,
130         0,
131         MONO_ASSEMBLY_SIZE,     /* 0x20 */
132         MONO_ASSEMBLY_PROCESSOR_SIZE,
133         MONO_ASSEMBLYOS_SIZE,
134         MONO_ASSEMBLYREF_SIZE,
135         MONO_ASSEMBLYREFPROC_SIZE,
136         MONO_ASSEMBLYREFOS_SIZE,
137         MONO_FILE_SIZE,
138         MONO_EXP_TYPE_SIZE,
139         MONO_MANIFEST_SIZE,
140         MONO_NESTED_CLASS_SIZE,
141
142         MONO_GENERICPARAM_SIZE, /* 0x2A */
143         MONO_METHODSPEC_SIZE,
144         MONO_GENPARCONSTRAINT_SIZE
145
146 };
147
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
161 #endif
162
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
189
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
193
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
196
197 #define RESOLVE_TYPE(type, error) do {                                  \
198         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
199 } while (0)
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
201         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202         __type = mono_reflection_type_resolve_user_types (__type, error); \
203         if (mono_error_ok (error))                                      \
204                 mono_array_set (arr, MonoReflectionType*, index, __type); \
205 } while (0)
206
207 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
208
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
211
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
214 #else
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
216 #endif
217
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
220
221 /* Class lazy loading functions */
222 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
223 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
232 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
233 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
234 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
236 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
237 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
238 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
239 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
240 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
241
242 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
243 static GPtrArray *dynamic_images;
244 static mono_mutex_t dynamic_images_mutex;
245
246 static inline void
247 dynamic_images_lock (void)
248 {
249         mono_os_mutex_lock (&dynamic_images_mutex);
250 }
251
252 static inline void
253 dynamic_images_unlock (void)
254 {
255         mono_os_mutex_unlock (&dynamic_images_mutex);
256 }
257
258 /**
259  * mono_find_dynamic_image_owner:
260  *
261  * Find the dynamic image, if any, which a given pointer is located in the memory of.
262  */
263 MonoImage *
264 mono_find_dynamic_image_owner (void *ptr)
265 {
266         MonoImage *owner = NULL;
267         int i;
268
269         dynamic_images_lock ();
270
271         if (dynamic_images)
272         {
273                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
274                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
275                         if (mono_mempool_contains_addr (image->mempool, ptr))
276                                 owner = image;
277                 }
278         }
279
280         dynamic_images_unlock ();
281
282         return owner;
283 }
284
285 void
286 mono_reflection_init (void)
287 {
288         mono_os_mutex_init (&dynamic_images_mutex);
289 }
290
291 static inline void
292 dynamic_image_lock (MonoDynamicImage *image)
293 {
294         MONO_PREPARE_BLOCKING;
295         mono_image_lock ((MonoImage*)image);
296         MONO_FINISH_BLOCKING;
297 }
298
299 static inline void
300 dynamic_image_unlock (MonoDynamicImage *image)
301 {
302         mono_image_unlock ((MonoImage*)image);
303 }
304
305 static void
306 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
307 {
308         MONO_REQ_GC_UNSAFE_MODE;
309
310         dynamic_image_lock (assembly);
311         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
312         dynamic_image_unlock (assembly);
313 }
314
315 static MonoObject*
316 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
317 {
318         MONO_REQ_GC_UNSAFE_MODE;
319
320         MonoObject *obj;
321
322         dynamic_image_lock (assembly);
323         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
324         dynamic_image_unlock (assembly);
325
326         return obj;
327 }
328
329 static void
330 sigbuffer_init (SigBuffer *buf, int size)
331 {
332         MONO_REQ_GC_NEUTRAL_MODE;
333
334         buf->buf = (char *)g_malloc (size);
335         buf->p = buf->buf;
336         buf->end = buf->buf + size;
337 }
338
339 static void
340 sigbuffer_make_room (SigBuffer *buf, int size)
341 {
342         MONO_REQ_GC_NEUTRAL_MODE;
343
344         if (buf->end - buf->p < size) {
345                 int new_size = buf->end - buf->buf + size + 32;
346                 char *p = (char *)g_realloc (buf->buf, new_size);
347                 size = buf->p - buf->buf;
348                 buf->buf = p;
349                 buf->p = p + size;
350                 buf->end = buf->buf + new_size;
351         }
352 }
353
354 static void
355 sigbuffer_add_value (SigBuffer *buf, guint32 val)
356 {
357         MONO_REQ_GC_NEUTRAL_MODE;
358
359         sigbuffer_make_room (buf, 6);
360         mono_metadata_encode_value (val, buf->p, &buf->p);
361 }
362
363 static void
364 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
365 {
366         MONO_REQ_GC_NEUTRAL_MODE;
367
368         sigbuffer_make_room (buf, 1);
369         buf->p [0] = val;
370         buf->p++;
371 }
372
373 static void
374 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
375 {
376         MONO_REQ_GC_NEUTRAL_MODE;
377
378         sigbuffer_make_room (buf, size);
379         memcpy (buf->p, p, size);
380         buf->p += size;
381 }
382
383 static void
384 sigbuffer_free (SigBuffer *buf)
385 {
386         MONO_REQ_GC_NEUTRAL_MODE;
387
388         g_free (buf->buf);
389 }
390
391 #ifndef DISABLE_REFLECTION_EMIT
392 /**
393  * mp_g_alloc:
394  *
395  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396  * from the C heap.
397  */
398 static gpointer
399 image_g_malloc (MonoImage *image, guint size)
400 {
401         MONO_REQ_GC_NEUTRAL_MODE;
402
403         if (image)
404                 return mono_image_alloc (image, size);
405         else
406                 return g_malloc (size);
407 }
408 #endif /* !DISABLE_REFLECTION_EMIT */
409
410 /**
411  * image_g_alloc0:
412  *
413  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
414  * from the C heap.
415  */
416 static gpointer
417 image_g_malloc0 (MonoImage *image, guint size)
418 {
419         MONO_REQ_GC_NEUTRAL_MODE;
420
421         if (image)
422                 return mono_image_alloc0 (image, size);
423         else
424                 return g_malloc0 (size);
425 }
426
427 /**
428  * image_g_free:
429  * @image: a MonoImage
430  * @ptr: pointer
431  *
432  * If @image is NULL, free @ptr, otherwise do nothing.
433  */
434 static void
435 image_g_free (MonoImage *image, gpointer ptr)
436 {
437         if (image == NULL)
438                 g_free (ptr);
439 }
440
441 #ifndef DISABLE_REFLECTION_EMIT
442 static char*
443 image_strdup (MonoImage *image, const char *s)
444 {
445         MONO_REQ_GC_NEUTRAL_MODE;
446
447         if (image)
448                 return mono_image_strdup (image, s);
449         else
450                 return g_strdup (s);
451 }
452 #endif
453
454 #define image_g_new(image,struct_type, n_structs)               \
455     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
456
457 #define image_g_new0(image,struct_type, n_structs)              \
458     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
459
460
461 static void
462 alloc_table (MonoDynamicTable *table, guint nrows)
463 {
464         MONO_REQ_GC_NEUTRAL_MODE;
465
466         table->rows = nrows;
467         g_assert (table->columns);
468         if (nrows + 1 >= table->alloc_rows) {
469                 while (nrows + 1 >= table->alloc_rows) {
470                         if (table->alloc_rows == 0)
471                                 table->alloc_rows = 16;
472                         else
473                                 table->alloc_rows *= 2;
474                 }
475
476                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
477         }
478 }
479
480 static void
481 make_room_in_stream (MonoDynamicStream *stream, int size)
482 {
483         MONO_REQ_GC_NEUTRAL_MODE;
484
485         if (size <= stream->alloc_size)
486                 return;
487         
488         while (stream->alloc_size <= size) {
489                 if (stream->alloc_size < 4096)
490                         stream->alloc_size = 4096;
491                 else
492                         stream->alloc_size *= 2;
493         }
494         
495         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
496 }
497
498 static guint32
499 string_heap_insert (MonoDynamicStream *sh, const char *str)
500 {
501         MONO_REQ_GC_NEUTRAL_MODE;
502
503         guint32 idx;
504         guint32 len;
505         gpointer oldkey, oldval;
506
507         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
508                 return GPOINTER_TO_UINT (oldval);
509
510         len = strlen (str) + 1;
511         idx = sh->index;
512         
513         make_room_in_stream (sh, idx + len);
514
515         /*
516          * We strdup the string even if we already copy them in sh->data
517          * so that the string pointers in the hash remain valid even if
518          * we need to realloc sh->data. We may want to avoid that later.
519          */
520         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
521         memcpy (sh->data + idx, str, len);
522         sh->index += len;
523         return idx;
524 }
525
526 static guint32
527 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
528 {
529         MONO_REQ_GC_UNSAFE_MODE;
530
531         char *name = mono_string_to_utf8 (str);
532         guint32 idx;
533         idx = string_heap_insert (sh, name);
534         g_free (name);
535         return idx;
536 }
537
538 #ifndef DISABLE_REFLECTION_EMIT
539 static void
540 string_heap_init (MonoDynamicStream *sh)
541 {
542         MONO_REQ_GC_NEUTRAL_MODE;
543
544         sh->index = 0;
545         sh->alloc_size = 4096;
546         sh->data = (char *)g_malloc (4096);
547         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
548         string_heap_insert (sh, "");
549 }
550 #endif
551
552 static guint32
553 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
554 {
555         MONO_REQ_GC_NEUTRAL_MODE;
556
557         guint32 idx;
558         
559         make_room_in_stream (stream, stream->index + len);
560         memcpy (stream->data + stream->index, data, len);
561         idx = stream->index;
562         stream->index += len;
563         /* 
564          * align index? Not without adding an additional param that controls it since
565          * we may store a blob value in pieces.
566          */
567         return idx;
568 }
569
570 static guint32
571 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
572 {
573         MONO_REQ_GC_NEUTRAL_MODE;
574
575         guint32 idx;
576         
577         make_room_in_stream (stream, stream->index + len);
578         memset (stream->data + stream->index, 0, len);
579         idx = stream->index;
580         stream->index += len;
581         return idx;
582 }
583
584 static void
585 stream_data_align (MonoDynamicStream *stream)
586 {
587         MONO_REQ_GC_NEUTRAL_MODE;
588
589         char buf [4] = {0};
590         guint32 count = stream->index % 4;
591
592         /* we assume the stream data will be aligned */
593         if (count)
594                 mono_image_add_stream_data (stream, buf, 4 - count);
595 }
596
597 #ifndef DISABLE_REFLECTION_EMIT
598 static int
599 mono_blob_entry_hash (const char* str)
600 {
601         MONO_REQ_GC_NEUTRAL_MODE;
602
603         guint len, h;
604         const char *end;
605         len = mono_metadata_decode_blob_size (str, &str);
606         if (len > 0) {
607                 end = str + len;
608                 h = *str;
609                 for (str += 1; str < end; str++)
610                         h = (h << 5) - h + *str;
611                 return h;
612         } else {
613                 return 0;
614         }
615 }
616
617 static gboolean
618 mono_blob_entry_equal (const char *str1, const char *str2) {
619         MONO_REQ_GC_NEUTRAL_MODE;
620
621         int len, len2;
622         const char *end1;
623         const char *end2;
624         len = mono_metadata_decode_blob_size (str1, &end1);
625         len2 = mono_metadata_decode_blob_size (str2, &end2);
626         if (len != len2)
627                 return 0;
628         return memcmp (end1, end2, len) == 0;
629 }
630 #endif
631 static guint32
632 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
633 {
634         MONO_REQ_GC_NEUTRAL_MODE;
635
636         guint32 idx;
637         char *copy;
638         gpointer oldkey, oldval;
639
640         copy = (char *)g_malloc (s1+s2);
641         memcpy (copy, b1, s1);
642         memcpy (copy + s1, b2, s2);
643         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
644                 g_free (copy);
645                 idx = GPOINTER_TO_UINT (oldval);
646         } else {
647                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
648                 mono_image_add_stream_data (&assembly->blob, b2, s2);
649                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
650         }
651         return idx;
652 }
653
654 static guint32
655 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
656 {
657         MONO_REQ_GC_NEUTRAL_MODE;
658
659         char blob_size [8];
660         char *b = blob_size;
661         guint32 size = buf->p - buf->buf;
662         /* store length */
663         g_assert (size <= (buf->end - buf->buf));
664         mono_metadata_encode_value (size, b, &b);
665         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
666 }
667
668 /*
669  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
670  * dest may be misaligned.
671  */
672 static void
673 swap_with_size (char *dest, const char* val, int len, int nelem) {
674         MONO_REQ_GC_NEUTRAL_MODE;
675 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
676         int elem;
677
678         for (elem = 0; elem < nelem; ++elem) {
679                 switch (len) {
680                 case 1:
681                         *dest = *val;
682                         break;
683                 case 2:
684                         dest [0] = val [1];
685                         dest [1] = val [0];
686                         break;
687                 case 4:
688                         dest [0] = val [3];
689                         dest [1] = val [2];
690                         dest [2] = val [1];
691                         dest [3] = val [0];
692                         break;
693                 case 8:
694                         dest [0] = val [7];
695                         dest [1] = val [6];
696                         dest [2] = val [5];
697                         dest [3] = val [4];
698                         dest [4] = val [3];
699                         dest [5] = val [2];
700                         dest [6] = val [1];
701                         dest [7] = val [0];
702                         break;
703                 default:
704                         g_assert_not_reached ();
705                 }
706                 dest += len;
707                 val += len;
708         }
709 #else
710         memcpy (dest, val, len * nelem);
711 #endif
712 }
713
714 static guint32
715 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
716 {
717         MONO_REQ_GC_UNSAFE_MODE;
718         
719         char blob_size [64];
720         char *b = blob_size;
721         guint32 idx = 0, len;
722
723         len = str->length * 2;
724         mono_metadata_encode_value (len, b, &b);
725 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
726         {
727                 char *swapped = g_malloc (2 * mono_string_length (str));
728                 const char *p = (const char*)mono_string_chars (str);
729
730                 swap_with_size (swapped, p, 2, mono_string_length (str));
731                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
732                 g_free (swapped);
733         }
734 #else
735         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
736 #endif
737         return idx;
738 }
739
740 #ifndef DISABLE_REFLECTION_EMIT
741 static MonoClass *
742 default_class_from_mono_type (MonoType *type)
743 {
744         MONO_REQ_GC_NEUTRAL_MODE;
745
746         switch (type->type) {
747         case MONO_TYPE_OBJECT:
748                 return mono_defaults.object_class;
749         case MONO_TYPE_VOID:
750                 return mono_defaults.void_class;
751         case MONO_TYPE_BOOLEAN:
752                 return mono_defaults.boolean_class;
753         case MONO_TYPE_CHAR:
754                 return mono_defaults.char_class;
755         case MONO_TYPE_I1:
756                 return mono_defaults.sbyte_class;
757         case MONO_TYPE_U1:
758                 return mono_defaults.byte_class;
759         case MONO_TYPE_I2:
760                 return mono_defaults.int16_class;
761         case MONO_TYPE_U2:
762                 return mono_defaults.uint16_class;
763         case MONO_TYPE_I4:
764                 return mono_defaults.int32_class;
765         case MONO_TYPE_U4:
766                 return mono_defaults.uint32_class;
767         case MONO_TYPE_I:
768                 return mono_defaults.int_class;
769         case MONO_TYPE_U:
770                 return mono_defaults.uint_class;
771         case MONO_TYPE_I8:
772                 return mono_defaults.int64_class;
773         case MONO_TYPE_U8:
774                 return mono_defaults.uint64_class;
775         case MONO_TYPE_R4:
776                 return mono_defaults.single_class;
777         case MONO_TYPE_R8:
778                 return mono_defaults.double_class;
779         case MONO_TYPE_STRING:
780                 return mono_defaults.string_class;
781         default:
782                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
783                 g_assert_not_reached ();
784         }
785         
786         return NULL;
787 }
788 #endif
789
790 /*
791  * mono_class_get_ref_info:
792  *
793  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
794  */
795 gpointer
796 mono_class_get_ref_info (MonoClass *klass)
797 {
798         MONO_REQ_GC_UNSAFE_MODE;
799
800         if (klass->ref_info_handle == 0)
801                 return NULL;
802         else
803                 return mono_gchandle_get_target (klass->ref_info_handle);
804 }
805
806 void
807 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
808 {
809         MONO_REQ_GC_UNSAFE_MODE;
810
811         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
812         g_assert (klass->ref_info_handle != 0);
813 }
814
815 void
816 mono_class_free_ref_info (MonoClass *klass)
817 {
818         MONO_REQ_GC_NEUTRAL_MODE;
819
820         if (klass->ref_info_handle) {
821                 mono_gchandle_free (klass->ref_info_handle);
822                 klass->ref_info_handle = 0;
823         }
824 }
825
826 static void
827 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
828 {
829         MONO_REQ_GC_NEUTRAL_MODE;
830
831         int i;
832         MonoGenericInst *class_inst;
833         MonoClass *klass;
834
835         g_assert (gclass);
836
837         class_inst = gclass->context.class_inst;
838
839         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
840         klass = gclass->container_class;
841         sigbuffer_add_value (buf, klass->byval_arg.type);
842         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
843
844         sigbuffer_add_value (buf, class_inst->type_argc);
845         for (i = 0; i < class_inst->type_argc; ++i)
846                 encode_type (assembly, class_inst->type_argv [i], buf);
847
848 }
849
850 static void
851 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
852 {
853         MONO_REQ_GC_NEUTRAL_MODE;
854
855         if (!type) {
856                 g_assert_not_reached ();
857                 return;
858         }
859                 
860         if (type->byref)
861                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
862
863         switch (type->type){
864         case MONO_TYPE_VOID:
865         case MONO_TYPE_BOOLEAN:
866         case MONO_TYPE_CHAR:
867         case MONO_TYPE_I1:
868         case MONO_TYPE_U1:
869         case MONO_TYPE_I2:
870         case MONO_TYPE_U2:
871         case MONO_TYPE_I4:
872         case MONO_TYPE_U4:
873         case MONO_TYPE_I8:
874         case MONO_TYPE_U8:
875         case MONO_TYPE_R4:
876         case MONO_TYPE_R8:
877         case MONO_TYPE_I:
878         case MONO_TYPE_U:
879         case MONO_TYPE_STRING:
880         case MONO_TYPE_OBJECT:
881         case MONO_TYPE_TYPEDBYREF:
882                 sigbuffer_add_value (buf, type->type);
883                 break;
884         case MONO_TYPE_PTR:
885                 sigbuffer_add_value (buf, type->type);
886                 encode_type (assembly, type->data.type, buf);
887                 break;
888         case MONO_TYPE_SZARRAY:
889                 sigbuffer_add_value (buf, type->type);
890                 encode_type (assembly, &type->data.klass->byval_arg, buf);
891                 break;
892         case MONO_TYPE_VALUETYPE:
893         case MONO_TYPE_CLASS: {
894                 MonoClass *k = mono_class_from_mono_type (type);
895
896                 if (k->generic_container) {
897                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
898                         encode_generic_class (assembly, gclass, buf);
899                 } else {
900                         /*
901                          * Make sure we use the correct type.
902                          */
903                         sigbuffer_add_value (buf, k->byval_arg.type);
904                         /*
905                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
906                          * otherwise two typerefs could point to the same type, leading to
907                          * verification errors.
908                          */
909                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
910                 }
911                 break;
912         }
913         case MONO_TYPE_ARRAY:
914                 sigbuffer_add_value (buf, type->type);
915                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
916                 sigbuffer_add_value (buf, type->data.array->rank);
917                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
918                 sigbuffer_add_value (buf, 0);
919                 break;
920         case MONO_TYPE_GENERICINST:
921                 encode_generic_class (assembly, type->data.generic_class, buf);
922                 break;
923         case MONO_TYPE_VAR:
924         case MONO_TYPE_MVAR:
925                 sigbuffer_add_value (buf, type->type);
926                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
927                 break;
928         default:
929                 g_error ("need to encode type %x", type->type);
930         }
931 }
932
933 static void
934 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
935 {
936         MONO_REQ_GC_UNSAFE_MODE;
937
938         mono_error_init (error);
939
940         if (!type) {
941                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
942                 return;
943         }
944
945         MonoType *t = mono_reflection_type_get_handle (type, error);
946         return_if_nok (error);
947         encode_type (assembly, t, buf);
948 }
949
950 static void
951 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
952 {
953         MONO_REQ_GC_UNSAFE_MODE;
954
955         int i;
956
957         mono_error_init (error);
958
959         if (modreq) {
960                 for (i = 0; i < mono_array_length (modreq); ++i) {
961                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
962                         return_if_nok (error);
963                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
964                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
965                 }
966         }
967         if (modopt) {
968                 for (i = 0; i < mono_array_length (modopt); ++i) {
969                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
970                         return_if_nok (error);
971                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
972                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
973                 }
974         }
975 }
976
977 #ifndef DISABLE_REFLECTION_EMIT
978 static guint32
979 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
980 {
981         MONO_REQ_GC_UNSAFE_MODE;
982
983         SigBuffer buf;
984         int i;
985         guint32 nparams =  sig->param_count;
986         guint32 idx;
987
988         if (!assembly->save)
989                 return 0;
990
991         sigbuffer_init (&buf, 32);
992         /*
993          * FIXME: vararg, explicit_this, differenc call_conv values...
994          */
995         idx = sig->call_convention;
996         if (sig->hasthis)
997                 idx |= 0x20; /* hasthis */
998         if (sig->generic_param_count)
999                 idx |= 0x10; /* generic */
1000         sigbuffer_add_byte (&buf, idx);
1001         if (sig->generic_param_count)
1002                 sigbuffer_add_value (&buf, sig->generic_param_count);
1003         sigbuffer_add_value (&buf, nparams);
1004         encode_type (assembly, sig->ret, &buf);
1005         for (i = 0; i < nparams; ++i) {
1006                 if (i == sig->sentinelpos)
1007                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1008                 encode_type (assembly, sig->params [i], &buf);
1009         }
1010         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1011         sigbuffer_free (&buf);
1012         return idx;
1013 }
1014 #endif
1015
1016 static guint32
1017 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1018 {
1019         MONO_REQ_GC_UNSAFE_MODE;
1020
1021         mono_error_init (error);
1022
1023         /*
1024          * FIXME: reuse code from method_encode_signature().
1025          */
1026         SigBuffer buf;
1027         int i;
1028         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1029         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1030         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1031         guint32 idx;
1032
1033         sigbuffer_init (&buf, 32);
1034         /* LAMESPEC: all the call conv spec is foobared */
1035         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1036         if (mb->call_conv & 2)
1037                 idx |= 0x5; /* vararg */
1038         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1039                 idx |= 0x20; /* hasthis */
1040         if (ngparams)
1041                 idx |= 0x10; /* generic */
1042         sigbuffer_add_byte (&buf, idx);
1043         if (ngparams)
1044                 sigbuffer_add_value (&buf, ngparams);
1045         sigbuffer_add_value (&buf, nparams + notypes);
1046         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1047         if (!is_ok (error))
1048                 goto leave;
1049         encode_reflection_type (assembly, mb->rtype, &buf, error);
1050         if (!is_ok (error))
1051                 goto leave;
1052         for (i = 0; i < nparams; ++i) {
1053                 MonoArray *modreq = NULL;
1054                 MonoArray *modopt = NULL;
1055                 MonoReflectionType *pt;
1056
1057                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1058                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1059                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1060                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1061                 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1062                 if (!is_ok (error))
1063                         goto leave;
1064                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1065                 encode_reflection_type (assembly, pt, &buf, error);
1066                 if (!is_ok (error))
1067                         goto leave;
1068         }
1069         if (notypes)
1070                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1071         for (i = 0; i < notypes; ++i) {
1072                 MonoReflectionType *pt;
1073
1074                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1075                 encode_reflection_type (assembly, pt, &buf, error);
1076                 if (!is_ok (error))
1077                         goto leave;
1078         }
1079
1080         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1081 leave:
1082         sigbuffer_free (&buf);
1083         return idx;
1084 }
1085
1086 static guint32
1087 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1088 {
1089         MONO_REQ_GC_UNSAFE_MODE;
1090
1091         mono_error_init (error);
1092
1093         MonoDynamicTable *table;
1094         guint32 *values;
1095         guint32 idx, sig_idx;
1096         guint nl = mono_array_length (ilgen->locals);
1097         SigBuffer buf;
1098         int i;
1099
1100         sigbuffer_init (&buf, 32);
1101         sigbuffer_add_value (&buf, 0x07);
1102         sigbuffer_add_value (&buf, nl);
1103         for (i = 0; i < nl; ++i) {
1104                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1105                 
1106                 if (lb->is_pinned)
1107                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1108                 
1109                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1110                 if (!is_ok (error)) {
1111                         sigbuffer_free (&buf);
1112                         return 0;
1113                 }
1114         }
1115         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1116         sigbuffer_free (&buf);
1117
1118         if (assembly->standalonesig_cache == NULL)
1119                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1120         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1121         if (idx)
1122                 return idx;
1123
1124         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1125         idx = table->next_idx ++;
1126         table->rows ++;
1127         alloc_table (table, table->rows);
1128         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1129
1130         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1131
1132         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1133
1134         return idx;
1135 }
1136
1137 static guint32
1138 method_count_clauses (MonoReflectionILGen *ilgen)
1139 {
1140         MONO_REQ_GC_UNSAFE_MODE;
1141
1142         guint32 num_clauses = 0;
1143         int i;
1144
1145         MonoILExceptionInfo *ex_info;
1146         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1147                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1148                 if (ex_info->handlers)
1149                         num_clauses += mono_array_length (ex_info->handlers);
1150                 else
1151                         num_clauses++;
1152         }
1153
1154         return num_clauses;
1155 }
1156
1157 #ifndef DISABLE_REFLECTION_EMIT
1158 static MonoExceptionClause*
1159 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1160 {
1161         MONO_REQ_GC_UNSAFE_MODE;
1162
1163         mono_error_init (error);
1164
1165         MonoExceptionClause *clauses;
1166         MonoExceptionClause *clause;
1167         MonoILExceptionInfo *ex_info;
1168         MonoILExceptionBlock *ex_block;
1169         guint32 finally_start;
1170         int i, j, clause_index;;
1171
1172         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1173
1174         clause_index = 0;
1175         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1176                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1177                 finally_start = ex_info->start + ex_info->len;
1178                 if (!ex_info->handlers)
1179                         continue;
1180                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1181                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1182                         clause = &(clauses [clause_index]);
1183
1184                         clause->flags = ex_block->type;
1185                         clause->try_offset = ex_info->start;
1186
1187                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1188                                 clause->try_len = finally_start - ex_info->start;
1189                         else
1190                                 clause->try_len = ex_info->len;
1191                         clause->handler_offset = ex_block->start;
1192                         clause->handler_len = ex_block->len;
1193                         if (ex_block->extype) {
1194                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1195
1196                                 if (!is_ok (error)) {
1197                                         image_g_free (image, clauses);
1198                                         return NULL;
1199                                 }
1200                                 clause->data.catch_class = mono_class_from_mono_type (extype);
1201                         } else {
1202                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1203                                         clause->data.filter_offset = ex_block->filter_offset;
1204                                 else
1205                                         clause->data.filter_offset = 0;
1206                         }
1207                         finally_start = ex_block->start + ex_block->len;
1208
1209                         clause_index ++;
1210                 }
1211         }
1212
1213         return clauses;
1214 }
1215 #endif /* !DISABLE_REFLECTION_EMIT */
1216
1217 /**
1218  * method_encode_code:
1219  *
1220  * @assembly the assembly
1221  * @mb the managed MethodBuilder
1222  * @error set on error
1223  *
1224  * Note that the return value is not sensible if @error is set.
1225  */
1226 static guint32
1227 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1228 {
1229         MONO_REQ_GC_UNSAFE_MODE;
1230
1231         char flags = 0;
1232         guint32 idx;
1233         guint32 code_size;
1234         gint32 max_stack, i;
1235         gint32 num_locals = 0;
1236         gint32 num_exception = 0;
1237         gint maybe_small;
1238         guint32 fat_flags;
1239         char fat_header [12];
1240         guint32 int_value;
1241         guint16 short_value;
1242         guint32 local_sig = 0;
1243         guint32 header_size = 12;
1244         MonoArray *code;
1245
1246         mono_error_init (error);
1247
1248         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1249                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1250                 return 0;
1251
1252         /*if (mb->name)
1253                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1254         if (mb->ilgen) {
1255                 code = mb->ilgen->code;
1256                 code_size = mb->ilgen->code_len;
1257                 max_stack = mb->ilgen->max_stack;
1258                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1259                 if (mb->ilgen->ex_handlers)
1260                         num_exception = method_count_clauses (mb->ilgen);
1261         } else {
1262                 code = mb->code;
1263                 if (code == NULL){
1264                         char *name = mono_string_to_utf8 (mb->name);
1265                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1266                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1267                         g_free (str);
1268                         g_free (name);
1269                         return 0;
1270                 }
1271
1272                 code_size = mono_array_length (code);
1273                 max_stack = 8; /* we probably need to run a verifier on the code... */
1274         }
1275
1276         stream_data_align (&assembly->code);
1277
1278         /* check for exceptions, maxstack, locals */
1279         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1280         if (maybe_small) {
1281                 if (code_size < 64 && !(code_size & 1)) {
1282                         flags = (code_size << 2) | 0x2;
1283                 } else if (code_size < 32 && (code_size & 1)) {
1284                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1285                 } else {
1286                         goto fat_header;
1287                 }
1288                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1289                 /* add to the fixup todo list */
1290                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1291                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1292                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1293                 return assembly->text_rva + idx;
1294         } 
1295 fat_header:
1296         if (num_locals) {
1297                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1298                 return_val_if_nok (error, 0);
1299         }
1300         /* 
1301          * FIXME: need to set also the header size in fat_flags.
1302          * (and more sects and init locals flags)
1303          */
1304         fat_flags =  0x03;
1305         if (num_exception)
1306                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1307         if (mb->init_locals)
1308                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1309         fat_header [0] = fat_flags;
1310         fat_header [1] = (header_size / 4 ) << 4;
1311         short_value = GUINT16_TO_LE (max_stack);
1312         memcpy (fat_header + 2, &short_value, 2);
1313         int_value = GUINT32_TO_LE (code_size);
1314         memcpy (fat_header + 4, &int_value, 4);
1315         int_value = GUINT32_TO_LE (local_sig);
1316         memcpy (fat_header + 8, &int_value, 4);
1317         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1318         /* add to the fixup todo list */
1319         if (mb->ilgen && mb->ilgen->num_token_fixups)
1320                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1321         
1322         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1323         if (num_exception) {
1324                 unsigned char sheader [4];
1325                 MonoILExceptionInfo * ex_info;
1326                 MonoILExceptionBlock * ex_block;
1327                 int j;
1328
1329                 stream_data_align (&assembly->code);
1330                 /* always use fat format for now */
1331                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1332                 num_exception *= 6 * sizeof (guint32);
1333                 num_exception += 4; /* include the size of the header */
1334                 sheader [1] = num_exception & 0xff;
1335                 sheader [2] = (num_exception >> 8) & 0xff;
1336                 sheader [3] = (num_exception >> 16) & 0xff;
1337                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1338                 /* fat header, so we are already aligned */
1339                 /* reverse order */
1340                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1341                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1342                         if (ex_info->handlers) {
1343                                 int finally_start = ex_info->start + ex_info->len;
1344                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1345                                         guint32 val;
1346                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1347                                         /* the flags */
1348                                         val = GUINT32_TO_LE (ex_block->type);
1349                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1350                                         /* try offset */
1351                                         val = GUINT32_TO_LE (ex_info->start);
1352                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1353                                         /* need fault, too, probably */
1354                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1355                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1356                                         else
1357                                                 val = GUINT32_TO_LE (ex_info->len);
1358                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1359                                         /* handler offset */
1360                                         val = GUINT32_TO_LE (ex_block->start);
1361                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1362                                         /* handler len */
1363                                         val = GUINT32_TO_LE (ex_block->len);
1364                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1365                                         finally_start = ex_block->start + ex_block->len;
1366                                         if (ex_block->extype) {
1367                                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1368                                                 return_val_if_nok (error, 0);
1369
1370                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1371                                         } else {
1372                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1373                                                         val = ex_block->filter_offset;
1374                                                 else
1375                                                         val = 0;
1376                                         }
1377                                         val = GUINT32_TO_LE (val);
1378                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1379                                         /*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", 
1380                                                         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);*/
1381                                 }
1382                         } else {
1383                                 g_error ("No clauses for ex info block %d", i);
1384                         }
1385                 }
1386         }
1387         return assembly->text_rva + idx;
1388 }
1389
1390 static guint32
1391 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1392 {
1393         MONO_REQ_GC_NEUTRAL_MODE;
1394
1395         int i;
1396         MonoDynamicTable *table;
1397         guint32 *values;
1398         
1399         table = &assembly->tables [table_idx];
1400
1401         g_assert (col < table->columns);
1402
1403         values = table->values + table->columns;
1404         for (i = 1; i <= table->rows; ++i) {
1405                 if (values [col] == token)
1406                         return i;
1407                 values += table->columns;
1408         }
1409         return 0;
1410 }
1411
1412 /*
1413  * LOCKING: Acquires the loader lock. 
1414  */
1415 static MonoCustomAttrInfo*
1416 lookup_custom_attr (MonoImage *image, gpointer member)
1417 {
1418         MONO_REQ_GC_NEUTRAL_MODE;
1419
1420         MonoCustomAttrInfo* res;
1421
1422         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1423
1424         if (!res)
1425                 return NULL;
1426
1427         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1428         res->cached = 0;
1429         return res;
1430 }
1431
1432 static gboolean
1433 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1434 {
1435         MONO_REQ_GC_UNSAFE_MODE;
1436
1437         /* FIXME: Need to do more checks */
1438         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1439                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1440
1441                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1442                         return FALSE;
1443         }
1444
1445         return TRUE;
1446 }
1447
1448 static MonoCustomAttrInfo*
1449 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1450 {
1451         MONO_REQ_GC_UNSAFE_MODE;
1452
1453         int i, index, count, not_visible;
1454         MonoCustomAttrInfo *ainfo;
1455         MonoReflectionCustomAttr *cattr;
1456
1457         if (!cattrs)
1458                 return NULL;
1459         /* FIXME: check in assembly the Run flag is set */
1460
1461         count = mono_array_length (cattrs);
1462
1463         /* Skip nonpublic attributes since MS.NET seems to do the same */
1464         /* FIXME: This needs to be done more globally */
1465         not_visible = 0;
1466         for (i = 0; i < count; ++i) {
1467                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1468                 if (!custom_attr_visible (image, cattr))
1469                         not_visible ++;
1470         }
1471         count -= not_visible;
1472
1473         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1474
1475         ainfo->image = image;
1476         ainfo->num_attrs = count;
1477         ainfo->cached = alloc_img != NULL;
1478         index = 0;
1479         for (i = 0; i < count; ++i) {
1480                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1481                 if (custom_attr_visible (image, cattr)) {
1482                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1483                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1484                         ainfo->attrs [index].ctor = cattr->ctor->method;
1485                         ainfo->attrs [index].data = saved;
1486                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1487                         index ++;
1488                 }
1489         }
1490
1491         return ainfo;
1492 }
1493
1494 #ifndef DISABLE_REFLECTION_EMIT
1495 /*
1496  * LOCKING: Acquires the loader lock. 
1497  */
1498 static void
1499 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1500 {
1501         MONO_REQ_GC_UNSAFE_MODE;
1502
1503         MonoCustomAttrInfo *ainfo, *tmp;
1504
1505         if (!cattrs || !mono_array_length (cattrs))
1506                 return;
1507
1508         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1509
1510         mono_loader_lock ();
1511         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1512         if (tmp)
1513                 mono_custom_attrs_free (tmp);
1514         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1515         mono_loader_unlock ();
1516
1517 }
1518 #endif
1519
1520 void
1521 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1522 {
1523         MONO_REQ_GC_NEUTRAL_MODE;
1524
1525         if (ainfo && !ainfo->cached)
1526                 g_free (ainfo);
1527 }
1528
1529 /*
1530  * idx is the table index of the object
1531  * type is one of MONO_CUSTOM_ATTR_*
1532  */
1533 static gboolean
1534 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1535 {
1536         MONO_REQ_GC_UNSAFE_MODE;
1537
1538         MonoDynamicTable *table;
1539         MonoReflectionCustomAttr *cattr;
1540         guint32 *values;
1541         guint32 count, i, token;
1542         char blob_size [6];
1543         char *p = blob_size;
1544         
1545         mono_error_init (error);
1546
1547         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1548         if (!cattrs)
1549                 return TRUE;
1550         count = mono_array_length (cattrs);
1551         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1552         table->rows += count;
1553         alloc_table (table, table->rows);
1554         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1555         idx <<= MONO_CUSTOM_ATTR_BITS;
1556         idx |= type;
1557         for (i = 0; i < count; ++i) {
1558                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1559                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1560                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1561                 if (!mono_error_ok (error)) goto fail;
1562                 type = mono_metadata_token_index (token);
1563                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1564                 switch (mono_metadata_token_table (token)) {
1565                 case MONO_TABLE_METHOD:
1566                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1567                         /*
1568                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1569                          * method, not the one returned by mono_image_create_token ().
1570                          */
1571                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1572                         break;
1573                 case MONO_TABLE_MEMBERREF:
1574                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1575                         break;
1576                 default:
1577                         g_warning ("got wrong token in custom attr");
1578                         continue;
1579                 }
1580                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1581                 p = blob_size;
1582                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1583                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1584                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1585                 values += MONO_CUSTOM_ATTR_SIZE;
1586                 ++table->next_idx;
1587         }
1588
1589         return TRUE;
1590
1591 fail:
1592         return FALSE;
1593 }
1594
1595 static void
1596 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1597 {
1598         MONO_REQ_GC_UNSAFE_MODE;
1599
1600         MonoDynamicTable *table;
1601         guint32 *values;
1602         guint32 count, i, idx;
1603         MonoReflectionPermissionSet *perm;
1604
1605         if (!permissions)
1606                 return;
1607
1608         count = mono_array_length (permissions);
1609         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1610         table->rows += count;
1611         alloc_table (table, table->rows);
1612
1613         for (i = 0; i < mono_array_length (permissions); ++i) {
1614                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1615
1616                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1617
1618                 idx = mono_metadata_token_index (parent_token);
1619                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1620                 switch (mono_metadata_token_table (parent_token)) {
1621                 case MONO_TABLE_TYPEDEF:
1622                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1623                         break;
1624                 case MONO_TABLE_METHOD:
1625                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1626                         break;
1627                 case MONO_TABLE_ASSEMBLY:
1628                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1629                         break;
1630                 default:
1631                         g_assert_not_reached ();
1632                 }
1633
1634                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1635                 values [MONO_DECL_SECURITY_PARENT] = idx;
1636                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1637
1638                 ++table->next_idx;
1639         }
1640 }
1641
1642 /*
1643  * Fill in the MethodDef and ParamDef tables for a method.
1644  * This is used for both normal methods and constructors.
1645  */
1646 static gboolean
1647 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1648 {
1649         MONO_REQ_GC_UNSAFE_MODE;
1650
1651         MonoDynamicTable *table;
1652         guint32 *values;
1653         guint i, count;
1654
1655         mono_error_init (error);
1656
1657         /* room in this table is already allocated */
1658         table = &assembly->tables [MONO_TABLE_METHOD];
1659         *mb->table_idx = table->next_idx ++;
1660         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1661         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1662         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1663         values [MONO_METHOD_FLAGS] = mb->attrs;
1664         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1665         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1666         return_val_if_nok (error, FALSE);
1667         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1668         return_val_if_nok (error, FALSE);
1669
1670         table = &assembly->tables [MONO_TABLE_PARAM];
1671         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1672
1673         mono_image_add_decl_security (assembly, 
1674                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1675
1676         if (mb->pinfo) {
1677                 MonoDynamicTable *mtable;
1678                 guint32 *mvalues;
1679                 
1680                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1681                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1682                 
1683                 count = 0;
1684                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1685                         if (mono_array_get (mb->pinfo, gpointer, i))
1686                                 count++;
1687                 }
1688                 table->rows += count;
1689                 alloc_table (table, table->rows);
1690                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1691                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1692                         MonoReflectionParamBuilder *pb;
1693                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1694                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1695                                 values [MONO_PARAM_SEQUENCE] = i;
1696                                 if (pb->name != NULL) {
1697                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1698                                 } else {
1699                                         values [MONO_PARAM_NAME] = 0;
1700                                 }
1701                                 values += MONO_PARAM_SIZE;
1702                                 if (pb->marshal_info) {
1703                                         mtable->rows++;
1704                                         alloc_table (mtable, mtable->rows);
1705                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1706                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1707                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1708                                         return_val_if_nok (error, FALSE);
1709                                 }
1710                                 pb->table_idx = table->next_idx++;
1711                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1712                                         guint32 field_type = 0;
1713                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1714                                         mtable->rows ++;
1715                                         alloc_table (mtable, mtable->rows);
1716                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1717                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1718                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1719                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1720                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1721                                 }
1722                         }
1723                 }
1724         }
1725
1726         return TRUE;
1727 }
1728
1729 #ifndef DISABLE_REFLECTION_EMIT
1730 static gboolean
1731 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1732 {
1733         MONO_REQ_GC_UNSAFE_MODE;
1734
1735         mono_error_init (error);
1736         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1737
1738         rmb->ilgen = mb->ilgen;
1739         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1740         return_val_if_nok (error, FALSE);
1741         rmb->parameters = mb->parameters;
1742         rmb->generic_params = mb->generic_params;
1743         rmb->generic_container = mb->generic_container;
1744         rmb->opt_types = NULL;
1745         rmb->pinfo = mb->pinfo;
1746         rmb->attrs = mb->attrs;
1747         rmb->iattrs = mb->iattrs;
1748         rmb->call_conv = mb->call_conv;
1749         rmb->code = mb->code;
1750         rmb->type = mb->type;
1751         rmb->name = mb->name;
1752         rmb->table_idx = &mb->table_idx;
1753         rmb->init_locals = mb->init_locals;
1754         rmb->skip_visibility = FALSE;
1755         rmb->return_modreq = mb->return_modreq;
1756         rmb->return_modopt = mb->return_modopt;
1757         rmb->param_modreq = mb->param_modreq;
1758         rmb->param_modopt = mb->param_modopt;
1759         rmb->permissions = mb->permissions;
1760         rmb->mhandle = mb->mhandle;
1761         rmb->nrefs = 0;
1762         rmb->refs = NULL;
1763
1764         if (mb->dll) {
1765                 rmb->charset = mb->charset;
1766                 rmb->extra_flags = mb->extra_flags;
1767                 rmb->native_cc = mb->native_cc;
1768                 rmb->dllentry = mb->dllentry;
1769                 rmb->dll = mb->dll;
1770         }
1771
1772         return TRUE;
1773 }
1774
1775 static gboolean
1776 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1777 {
1778         MONO_REQ_GC_UNSAFE_MODE;
1779
1780         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1781
1782         mono_error_init (error);
1783
1784         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1785
1786         rmb->ilgen = mb->ilgen;
1787         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1788         return_val_if_nok (error, FALSE);
1789         rmb->parameters = mb->parameters;
1790         rmb->generic_params = NULL;
1791         rmb->generic_container = NULL;
1792         rmb->opt_types = NULL;
1793         rmb->pinfo = mb->pinfo;
1794         rmb->attrs = mb->attrs;
1795         rmb->iattrs = mb->iattrs;
1796         rmb->call_conv = mb->call_conv;
1797         rmb->code = NULL;
1798         rmb->type = mb->type;
1799         rmb->name = mono_string_new (mono_domain_get (), name);
1800         rmb->table_idx = &mb->table_idx;
1801         rmb->init_locals = mb->init_locals;
1802         rmb->skip_visibility = FALSE;
1803         rmb->return_modreq = NULL;
1804         rmb->return_modopt = NULL;
1805         rmb->param_modreq = mb->param_modreq;
1806         rmb->param_modopt = mb->param_modopt;
1807         rmb->permissions = mb->permissions;
1808         rmb->mhandle = mb->mhandle;
1809         rmb->nrefs = 0;
1810         rmb->refs = NULL;
1811
1812         return TRUE;
1813 }
1814
1815 static void
1816 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1817 {
1818         MONO_REQ_GC_UNSAFE_MODE;
1819
1820         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1821
1822         rmb->ilgen = mb->ilgen;
1823         rmb->rtype = mb->rtype;
1824         rmb->parameters = mb->parameters;
1825         rmb->generic_params = NULL;
1826         rmb->generic_container = NULL;
1827         rmb->opt_types = NULL;
1828         rmb->pinfo = NULL;
1829         rmb->attrs = mb->attrs;
1830         rmb->iattrs = 0;
1831         rmb->call_conv = mb->call_conv;
1832         rmb->code = NULL;
1833         rmb->type = (MonoObject *) mb->owner;
1834         rmb->name = mb->name;
1835         rmb->table_idx = NULL;
1836         rmb->init_locals = mb->init_locals;
1837         rmb->skip_visibility = mb->skip_visibility;
1838         rmb->return_modreq = NULL;
1839         rmb->return_modopt = NULL;
1840         rmb->param_modreq = NULL;
1841         rmb->param_modopt = NULL;
1842         rmb->permissions = NULL;
1843         rmb->mhandle = mb->mhandle;
1844         rmb->nrefs = 0;
1845         rmb->refs = NULL;
1846 }       
1847 #endif
1848
1849 static gboolean
1850 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1851 {
1852         MONO_REQ_GC_UNSAFE_MODE;
1853
1854         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1855         MonoDynamicTable *table;
1856         guint32 *values;
1857         guint32 tok;
1858         MonoReflectionMethod *m;
1859         int i;
1860
1861         mono_error_init (error);
1862
1863         if (!mb->override_methods)
1864                 return TRUE;
1865
1866         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1867                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1868
1869                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1870                 table->rows ++;
1871                 alloc_table (table, table->rows);
1872                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1873                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1874                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1875
1876                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1877                 return_val_if_nok (error, FALSE);
1878
1879                 switch (mono_metadata_token_table (tok)) {
1880                 case MONO_TABLE_MEMBERREF:
1881                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1882                         break;
1883                 case MONO_TABLE_METHOD:
1884                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1885                         break;
1886                 default:
1887                         g_assert_not_reached ();
1888                 }
1889                 values [MONO_METHODIMPL_DECLARATION] = tok;
1890         }
1891
1892         return TRUE;
1893 }
1894
1895 #ifndef DISABLE_REFLECTION_EMIT
1896 static gboolean
1897 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1898 {
1899         MONO_REQ_GC_UNSAFE_MODE;
1900
1901         MonoDynamicTable *table;
1902         guint32 *values;
1903         ReflectionMethodBuilder rmb;
1904         int i;
1905
1906         mono_error_init (error);
1907
1908         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1909             !mono_image_basic_method (&rmb, assembly, error))
1910                 return FALSE;
1911
1912         mb->table_idx = *rmb.table_idx;
1913
1914         if (mb->dll) { /* It's a P/Invoke method */
1915                 guint32 moduleref;
1916                 /* map CharSet values to on-disk values */
1917                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1918                 int extra_flags = mb->extra_flags;
1919                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1920                 table->rows ++;
1921                 alloc_table (table, table->rows);
1922                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1923                 
1924                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1925                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1926                 if (mb->dllentry)
1927                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1928                 else
1929                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1930                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1931                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1932                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1933                         table->rows ++;
1934                         alloc_table (table, table->rows);
1935                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1936                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1937                 }
1938         }
1939
1940         if (mb->generic_params) {
1941                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1942                 table->rows += mono_array_length (mb->generic_params);
1943                 alloc_table (table, table->rows);
1944                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1945                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1946
1947                         mono_image_get_generic_param_info (
1948                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1949                 }
1950         }
1951
1952         return TRUE;
1953 }
1954
1955 static gboolean
1956 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1957 {
1958         MONO_REQ_GC_UNSAFE_MODE;
1959
1960         ReflectionMethodBuilder rmb;
1961
1962         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1963                 return FALSE;
1964
1965         if (!mono_image_basic_method (&rmb, assembly, error))
1966                 return FALSE;
1967
1968         mb->table_idx = *rmb.table_idx;
1969
1970         return TRUE;
1971 }
1972 #endif
1973
1974 static char*
1975 type_get_fully_qualified_name (MonoType *type)
1976 {
1977         MONO_REQ_GC_NEUTRAL_MODE;
1978
1979         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1980 }
1981
1982 static char*
1983 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1984 {
1985         MONO_REQ_GC_UNSAFE_MODE;
1986
1987         MonoClass *klass;
1988         MonoAssembly *ta;
1989
1990         klass = mono_class_from_mono_type (type);
1991         if (!klass) 
1992                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1993         ta = klass->image->assembly;
1994         if (assembly_is_dynamic (ta) || (ta == ass)) {
1995                 if (klass->generic_class || klass->generic_container)
1996                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1997                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1998                 else
1999                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2000         }
2001
2002         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2003 }
2004
2005 #ifndef DISABLE_REFLECTION_EMIT
2006 /*field_image is the image to which the eventual custom mods have been encoded against*/
2007 static guint32
2008 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2009 {
2010         MONO_REQ_GC_NEUTRAL_MODE;
2011
2012         SigBuffer buf;
2013         guint32 idx, i, token;
2014
2015         if (!assembly->save)
2016                 return 0;
2017
2018         sigbuffer_init (&buf, 32);
2019         
2020         sigbuffer_add_value (&buf, 0x06);
2021         /* encode custom attributes before the type */
2022         if (type->num_mods) {
2023                 for (i = 0; i < type->num_mods; ++i) {
2024                         if (field_image) {
2025                                 MonoError error;
2026                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2027                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2028
2029                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2030                         } else {
2031                                 token = type->modifiers [i].token;
2032                         }
2033
2034                         if (type->modifiers [i].required)
2035                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2036                         else
2037                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2038
2039                         sigbuffer_add_value (&buf, token);
2040                 }
2041         }
2042         encode_type (assembly, type, &buf);
2043         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2044         sigbuffer_free (&buf);
2045         return idx;
2046 }
2047 #endif
2048
2049 static guint32
2050 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2051 {
2052         MONO_REQ_GC_UNSAFE_MODE;
2053
2054         mono_error_init (error);
2055
2056         SigBuffer buf;
2057         guint32 idx;
2058         guint32 typespec = 0;
2059         MonoType *type;
2060         MonoClass *klass;
2061
2062         init_type_builder_generics (fb->type);
2063
2064         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2065         return_val_if_nok (error, 0);
2066         klass = mono_class_from_mono_type (type);
2067
2068         sigbuffer_init (&buf, 32);
2069         
2070         sigbuffer_add_value (&buf, 0x06);
2071         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2072         if (!is_ok (error))
2073                 goto fail;
2074         /* encode custom attributes before the type */
2075
2076         if (klass->generic_container)
2077                 typespec = create_typespec (assembly, type);
2078
2079         if (typespec) {
2080                 MonoGenericClass *gclass;
2081                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2082                 encode_generic_class (assembly, gclass, &buf);
2083         } else {
2084                 encode_type (assembly, type, &buf);
2085         }
2086         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2087         sigbuffer_free (&buf);
2088         return idx;
2089 fail:
2090         sigbuffer_free (&buf);
2091         return 0;
2092 }
2093
2094 static guint32
2095 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2096 {
2097         MONO_REQ_GC_UNSAFE_MODE;
2098
2099         char blob_size [64];
2100         char *b = blob_size;
2101         char *box_val;
2102         char* buf;
2103         guint32 idx = 0, len = 0, dummy = 0;
2104
2105         buf = (char *)g_malloc (64);
2106         if (!val) {
2107                 *ret_type = MONO_TYPE_CLASS;
2108                 len = 4;
2109                 box_val = (char*)&dummy;
2110         } else {
2111                 box_val = ((char*)val) + sizeof (MonoObject);
2112                 *ret_type = val->vtable->klass->byval_arg.type;
2113         }
2114 handle_enum:
2115         switch (*ret_type) {
2116         case MONO_TYPE_BOOLEAN:
2117         case MONO_TYPE_U1:
2118         case MONO_TYPE_I1:
2119                 len = 1;
2120                 break;
2121         case MONO_TYPE_CHAR:
2122         case MONO_TYPE_U2:
2123         case MONO_TYPE_I2:
2124                 len = 2;
2125                 break;
2126         case MONO_TYPE_U4:
2127         case MONO_TYPE_I4:
2128         case MONO_TYPE_R4:
2129                 len = 4;
2130                 break;
2131         case MONO_TYPE_U8:
2132         case MONO_TYPE_I8:
2133                 len = 8;
2134                 break;
2135         case MONO_TYPE_R8:
2136                 len = 8;
2137                 break;
2138         case MONO_TYPE_VALUETYPE: {
2139                 MonoClass *klass = val->vtable->klass;
2140                 
2141                 if (klass->enumtype) {
2142                         *ret_type = mono_class_enum_basetype (klass)->type;
2143                         goto handle_enum;
2144                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2145                         len = 8;
2146                 } else 
2147                         g_error ("we can't encode valuetypes, we should have never reached this line");
2148                 break;
2149         }
2150         case MONO_TYPE_CLASS:
2151                 break;
2152         case MONO_TYPE_STRING: {
2153                 MonoString *str = (MonoString*)val;
2154                 /* there is no signature */
2155                 len = str->length * 2;
2156                 mono_metadata_encode_value (len, b, &b);
2157 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2158                 {
2159                         char *swapped = g_malloc (2 * mono_string_length (str));
2160                         const char *p = (const char*)mono_string_chars (str);
2161
2162                         swap_with_size (swapped, p, 2, mono_string_length (str));
2163                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2164                         g_free (swapped);
2165                 }
2166 #else
2167                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2168 #endif
2169
2170                 g_free (buf);
2171                 return idx;
2172         }
2173         case MONO_TYPE_GENERICINST:
2174                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2175                 goto handle_enum;
2176         default:
2177                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2178         }
2179
2180         /* there is no signature */
2181         mono_metadata_encode_value (len, b, &b);
2182 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2183         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2184         swap_with_size (blob_size, box_val, len, 1);
2185         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2186 #else
2187         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2188 #endif
2189
2190         g_free (buf);
2191         return idx;
2192 }
2193
2194 static guint32
2195 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2196 {
2197         MONO_REQ_GC_UNSAFE_MODE;
2198
2199         mono_error_init (error);
2200
2201         char *str;
2202         SigBuffer buf;
2203         guint32 idx, len;
2204
2205         sigbuffer_init (&buf, 32);
2206
2207         sigbuffer_add_value (&buf, minfo->type);
2208
2209         switch (minfo->type) {
2210         case MONO_NATIVE_BYVALTSTR:
2211         case MONO_NATIVE_BYVALARRAY:
2212                 sigbuffer_add_value (&buf, minfo->count);
2213                 break;
2214         case MONO_NATIVE_LPARRAY:
2215                 if (minfo->eltype || minfo->has_size) {
2216                         sigbuffer_add_value (&buf, minfo->eltype);
2217                         if (minfo->has_size) {
2218                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2219                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2220
2221                                 /* LAMESPEC: ElemMult is undocumented */
2222                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2223                         }
2224                 }
2225                 break;
2226         case MONO_NATIVE_SAFEARRAY:
2227                 if (minfo->eltype)
2228                         sigbuffer_add_value (&buf, minfo->eltype);
2229                 break;
2230         case MONO_NATIVE_CUSTOM:
2231                 if (minfo->guid) {
2232                         str = mono_string_to_utf8 (minfo->guid);
2233                         len = strlen (str);
2234                         sigbuffer_add_value (&buf, len);
2235                         sigbuffer_add_mem (&buf, str, len);
2236                         g_free (str);
2237                 } else {
2238                         sigbuffer_add_value (&buf, 0);
2239                 }
2240                 /* native type name */
2241                 sigbuffer_add_value (&buf, 0);
2242                 /* custom marshaler type name */
2243                 if (minfo->marshaltype || minfo->marshaltyperef) {
2244                         if (minfo->marshaltyperef) {
2245                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2246                                 if (!is_ok (error)) {
2247                                         sigbuffer_free (&buf);
2248                                         return 0;
2249                                 }
2250                                 str = type_get_fully_qualified_name (marshaltype);
2251                         } else
2252                                 str = mono_string_to_utf8 (minfo->marshaltype);
2253                         len = strlen (str);
2254                         sigbuffer_add_value (&buf, len);
2255                         sigbuffer_add_mem (&buf, str, len);
2256                         g_free (str);
2257                 } else {
2258                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2259                         sigbuffer_add_value (&buf, 0);
2260                 }
2261                 if (minfo->mcookie) {
2262                         str = mono_string_to_utf8 (minfo->mcookie);
2263                         len = strlen (str);
2264                         sigbuffer_add_value (&buf, len);
2265                         sigbuffer_add_mem (&buf, str, len);
2266                         g_free (str);
2267                 } else {
2268                         sigbuffer_add_value (&buf, 0);
2269                 }
2270                 break;
2271         default:
2272                 break;
2273         }
2274         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2275         sigbuffer_free (&buf);
2276         return idx;
2277 }
2278
2279 static void
2280 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2281 {
2282         MONO_REQ_GC_UNSAFE_MODE;
2283
2284         mono_error_init (error);
2285
2286         MonoDynamicTable *table;
2287         guint32 *values;
2288
2289         /* maybe this fixup should be done in the C# code */
2290         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2291                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2292         table = &assembly->tables [MONO_TABLE_FIELD];
2293         fb->table_idx = table->next_idx ++;
2294         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2295         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2296         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2297         values [MONO_FIELD_FLAGS] = fb->attrs;
2298         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2299         return_if_nok (error);
2300
2301
2302         if (fb->offset != -1) {
2303                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2304                 table->rows ++;
2305                 alloc_table (table, table->rows);
2306                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2307                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2308                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2309         }
2310         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2311                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2312                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2313                 table->rows ++;
2314                 alloc_table (table, table->rows);
2315                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2316                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2317                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2318                 values [MONO_CONSTANT_TYPE] = field_type;
2319                 values [MONO_CONSTANT_PADDING] = 0;
2320         }
2321         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2322                 guint32 rva_idx;
2323                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2324                 table->rows ++;
2325                 alloc_table (table, table->rows);
2326                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2327                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2328                 /*
2329                  * We store it in the code section because it's simpler for now.
2330                  */
2331                 if (fb->rva_data) {
2332                         if (mono_array_length (fb->rva_data) >= 10)
2333                                 stream_data_align (&assembly->code);
2334                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2335                 } else
2336                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2337                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2338         }
2339         if (fb->marshal_info) {
2340                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2341                 table->rows ++;
2342                 alloc_table (table, table->rows);
2343                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2344                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2345                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2346                 return_if_nok (error);
2347         }
2348 }
2349
2350 static guint32
2351 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2352 {
2353         MONO_REQ_GC_UNSAFE_MODE;
2354
2355         mono_error_init (error);
2356
2357         SigBuffer buf;
2358         guint32 nparams = 0;
2359         MonoReflectionMethodBuilder *mb = fb->get_method;
2360         MonoReflectionMethodBuilder *smb = fb->set_method;
2361         guint32 idx, i;
2362
2363         if (mb && mb->parameters)
2364                 nparams = mono_array_length (mb->parameters);
2365         if (!mb && smb && smb->parameters)
2366                 nparams = mono_array_length (smb->parameters) - 1;
2367         sigbuffer_init (&buf, 32);
2368         if (fb->call_conv & 0x20)
2369                 sigbuffer_add_byte (&buf, 0x28);
2370         else
2371                 sigbuffer_add_byte (&buf, 0x08);
2372         sigbuffer_add_value (&buf, nparams);
2373         if (mb) {
2374                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2375                 if (!is_ok (error))
2376                         goto fail;
2377                 for (i = 0; i < nparams; ++i) {
2378                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2379                         encode_reflection_type (assembly, pt, &buf, error);
2380                         if (!is_ok (error))
2381                                 goto fail;
2382                 }
2383         } else if (smb && smb->parameters) {
2384                 /* the property type is the last param */
2385                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2386                 if (!is_ok (error))
2387                         goto fail;
2388
2389                 for (i = 0; i < nparams; ++i) {
2390                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2391                         encode_reflection_type (assembly, pt, &buf, error);
2392                         if (!is_ok (error))
2393                                 goto fail;
2394                 }
2395         } else {
2396                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2397                 if (!is_ok (error))
2398                         goto fail;
2399         }
2400
2401         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2402         sigbuffer_free (&buf);
2403         return idx;
2404 fail:
2405         sigbuffer_free (&buf);
2406         return 0;
2407 }
2408
2409 static void
2410 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2411 {
2412         MONO_REQ_GC_UNSAFE_MODE;
2413
2414         mono_error_init (error);
2415
2416         MonoDynamicTable *table;
2417         guint32 *values;
2418         guint num_methods = 0;
2419         guint32 semaidx;
2420
2421         /* 
2422          * we need to set things in the following tables:
2423          * PROPERTYMAP (info already filled in _get_type_info ())
2424          * PROPERTY    (rows already preallocated in _get_type_info ())
2425          * METHOD      (method info already done with the generic method code)
2426          * METHODSEMANTICS
2427          * CONSTANT
2428          */
2429         table = &assembly->tables [MONO_TABLE_PROPERTY];
2430         pb->table_idx = table->next_idx ++;
2431         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2432         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2433         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2434         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2435         return_if_nok (error);
2436
2437
2438         /* FIXME: we still don't handle 'other' methods */
2439         if (pb->get_method) num_methods ++;
2440         if (pb->set_method) num_methods ++;
2441
2442         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2443         table->rows += num_methods;
2444         alloc_table (table, table->rows);
2445
2446         if (pb->get_method) {
2447                 semaidx = table->next_idx ++;
2448                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2449                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2450                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2451                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2452         }
2453         if (pb->set_method) {
2454                 semaidx = table->next_idx ++;
2455                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2456                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2457                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2458                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2459         }
2460         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2461                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2462                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2463                 table->rows ++;
2464                 alloc_table (table, table->rows);
2465                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2466                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2467                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2468                 values [MONO_CONSTANT_TYPE] = field_type;
2469                 values [MONO_CONSTANT_PADDING] = 0;
2470         }
2471 }
2472
2473 static void
2474 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2475 {
2476         MONO_REQ_GC_UNSAFE_MODE;
2477
2478         MonoDynamicTable *table;
2479         guint32 *values;
2480         guint num_methods = 0;
2481         guint32 semaidx;
2482
2483         /* 
2484          * we need to set things in the following tables:
2485          * EVENTMAP (info already filled in _get_type_info ())
2486          * EVENT    (rows already preallocated in _get_type_info ())
2487          * METHOD      (method info already done with the generic method code)
2488          * METHODSEMANTICS
2489          */
2490         table = &assembly->tables [MONO_TABLE_EVENT];
2491         eb->table_idx = table->next_idx ++;
2492         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2493         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2494         values [MONO_EVENT_FLAGS] = eb->attrs;
2495         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2496         return_if_nok (error);
2497         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2498
2499         /*
2500          * FIXME: we still don't handle 'other' methods 
2501          */
2502         if (eb->add_method) num_methods ++;
2503         if (eb->remove_method) num_methods ++;
2504         if (eb->raise_method) num_methods ++;
2505
2506         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2507         table->rows += num_methods;
2508         alloc_table (table, table->rows);
2509
2510         if (eb->add_method) {
2511                 semaidx = table->next_idx ++;
2512                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2513                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2514                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2515                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2516         }
2517         if (eb->remove_method) {
2518                 semaidx = table->next_idx ++;
2519                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2520                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2521                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2522                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2523         }
2524         if (eb->raise_method) {
2525                 semaidx = table->next_idx ++;
2526                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2527                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2528                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2529                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2530         }
2531 }
2532
2533 static void
2534 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2535 {
2536         MONO_REQ_GC_UNSAFE_MODE;
2537
2538         mono_error_init (error);
2539
2540         MonoDynamicTable *table;
2541         guint32 num_constraints, i;
2542         guint32 *values;
2543         guint32 table_idx;
2544
2545         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2546         num_constraints = gparam->iface_constraints ?
2547                 mono_array_length (gparam->iface_constraints) : 0;
2548         table->rows += num_constraints;
2549         if (gparam->base_type)
2550                 table->rows++;
2551         alloc_table (table, table->rows);
2552
2553         if (gparam->base_type) {
2554                 table_idx = table->next_idx ++;
2555                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2556
2557                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2558                 return_if_nok (error);
2559                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2560                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2561         }
2562
2563         for (i = 0; i < num_constraints; i++) {
2564                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2565                         gparam->iface_constraints, gpointer, i);
2566
2567                 table_idx = table->next_idx ++;
2568                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2569
2570                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2571                 return_if_nok (error);
2572
2573                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2574                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2575         }
2576 }
2577
2578 static void
2579 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2580 {
2581         MONO_REQ_GC_UNSAFE_MODE;
2582
2583         GenericParamTableEntry *entry;
2584
2585         /*
2586          * The GenericParam table must be sorted according to the `owner' field.
2587          * We need to do this sorting prior to writing the GenericParamConstraint
2588          * table, since we have to use the final GenericParam table indices there
2589          * and they must also be sorted.
2590          */
2591
2592         entry = g_new0 (GenericParamTableEntry, 1);
2593         entry->owner = owner;
2594         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2595         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2596         entry->gparam = gparam;
2597         
2598         g_ptr_array_add (assembly->gen_params, entry);
2599 }
2600
2601 static gboolean
2602 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2603 {
2604         MONO_REQ_GC_UNSAFE_MODE;
2605
2606         MonoDynamicTable *table;
2607         MonoGenericParam *param;
2608         guint32 *values;
2609         guint32 table_idx;
2610
2611         mono_error_init (error);
2612
2613         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2614         table_idx = table->next_idx ++;
2615         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2616
2617         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2618         return_val_if_nok (error, FALSE);
2619
2620         param = gparam_type->data.generic_param;
2621
2622         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2623         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2624         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2625         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2626
2627         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2628                 return FALSE;
2629
2630         encode_constraints (entry->gparam, table_idx, assembly, error);
2631         return_val_if_nok (error, FALSE);
2632
2633         return TRUE;
2634 }
2635
2636 static guint32
2637 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2638 {
2639         MONO_REQ_GC_UNSAFE_MODE;
2640
2641         MonoDynamicTable *table;
2642         guint32 token;
2643         guint32 *values;
2644         guint32 cols [MONO_ASSEMBLY_SIZE];
2645         const char *pubkey;
2646         guint32 publen;
2647
2648         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2649                 return token;
2650
2651         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2652                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2653                 token = table->next_idx ++;
2654                 table->rows ++;
2655                 alloc_table (table, table->rows);
2656                 values = table->values + token * MONO_MODULEREF_SIZE;
2657                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2658
2659                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2660                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2661                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2662
2663                 return token;
2664         }
2665         
2666         if (assembly_is_dynamic (image->assembly))
2667                 /* FIXME: */
2668                 memset (cols, 0, sizeof (cols));
2669         else {
2670                 /* image->assembly->image is the manifest module */
2671                 image = image->assembly->image;
2672                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2673         }
2674
2675         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2676         token = table->next_idx ++;
2677         table->rows ++;
2678         alloc_table (table, table->rows);
2679         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2680         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2681         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2682         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2683         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2684         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2685         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2686         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2687         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2688
2689         if (strcmp ("", image->assembly->aname.culture)) {
2690                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2691                                 image->assembly->aname.culture);
2692         }
2693
2694         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2695                 guchar pubtoken [9];
2696                 pubtoken [0] = 8;
2697                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2698                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2699         } else {
2700                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2701         }
2702         token <<= MONO_RESOLUTION_SCOPE_BITS;
2703         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2704         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2705         return token;
2706 }
2707
2708 static guint32
2709 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2710 {
2711         MONO_REQ_GC_NEUTRAL_MODE;
2712
2713         MonoDynamicTable *table;
2714         guint32 *values;
2715         guint32 token;
2716         SigBuffer buf;
2717
2718         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2719                 return token;
2720
2721         sigbuffer_init (&buf, 32);
2722         switch (type->type) {
2723         case MONO_TYPE_FNPTR:
2724         case MONO_TYPE_PTR:
2725         case MONO_TYPE_SZARRAY:
2726         case MONO_TYPE_ARRAY:
2727         case MONO_TYPE_VAR:
2728         case MONO_TYPE_MVAR:
2729         case MONO_TYPE_GENERICINST:
2730                 encode_type (assembly, type, &buf);
2731                 break;
2732         case MONO_TYPE_CLASS:
2733         case MONO_TYPE_VALUETYPE: {
2734                 MonoClass *k = mono_class_from_mono_type (type);
2735                 if (!k || !k->generic_container) {
2736                         sigbuffer_free (&buf);
2737                         return 0;
2738                 }
2739                 encode_type (assembly, type, &buf);
2740                 break;
2741         }
2742         default:
2743                 sigbuffer_free (&buf);
2744                 return 0;
2745         }
2746
2747         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2748         if (assembly->save) {
2749                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2750                 alloc_table (table, table->rows + 1);
2751                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2752                 values [MONO_TYPESPEC_SIGNATURE] = token;
2753         }
2754         sigbuffer_free (&buf);
2755
2756         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2757         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2758         table->next_idx ++;
2759         return token;
2760 }
2761
2762 static guint32
2763 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2764 {
2765         MONO_REQ_GC_UNSAFE_MODE;
2766
2767         MonoDynamicTable *table;
2768         guint32 *values;
2769         guint32 token, scope, enclosing;
2770         MonoClass *klass;
2771
2772         /* if the type requires a typespec, we must try that first*/
2773         if (try_typespec && (token = create_typespec (assembly, type)))
2774                 return token;
2775         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2776         if (token)
2777                 return token;
2778         klass = mono_class_from_mono_type (type);
2779         if (!klass)
2780                 klass = mono_class_from_mono_type (type);
2781
2782         /*
2783          * If it's in the same module and not a generic type parameter:
2784          */
2785         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2786                         (type->type != MONO_TYPE_MVAR)) {
2787                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2788                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2789                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2790                 return token;
2791         }
2792
2793         if (klass->nested_in) {
2794                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2795                 /* get the typeref idx of the enclosing type */
2796                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2797                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2798         } else {
2799                 scope = resolution_scope_from_image (assembly, klass->image);
2800         }
2801         table = &assembly->tables [MONO_TABLE_TYPEREF];
2802         if (assembly->save) {
2803                 alloc_table (table, table->rows + 1);
2804                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2805                 values [MONO_TYPEREF_SCOPE] = scope;
2806                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2807                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2808         }
2809         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2810         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2811         table->next_idx ++;
2812         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2813         return token;
2814 }
2815
2816 /*
2817  * Despite the name, we handle also TypeSpec (with the above helper).
2818  */
2819 static guint32
2820 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2821 {
2822         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2823 }
2824
2825 #ifndef DISABLE_REFLECTION_EMIT
2826 static guint32
2827 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2828 {
2829         MONO_REQ_GC_NEUTRAL_MODE;
2830
2831         MonoDynamicTable *table;
2832         guint32 *values;
2833         guint32 token, pclass;
2834
2835         switch (parent & MONO_TYPEDEFORREF_MASK) {
2836         case MONO_TYPEDEFORREF_TYPEREF:
2837                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2838                 break;
2839         case MONO_TYPEDEFORREF_TYPESPEC:
2840                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2841                 break;
2842         case MONO_TYPEDEFORREF_TYPEDEF:
2843                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2844                 break;
2845         default:
2846                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2847                 return 0;
2848         }
2849         /* extract the index */
2850         parent >>= MONO_TYPEDEFORREF_BITS;
2851
2852         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2853
2854         if (assembly->save) {
2855                 alloc_table (table, table->rows + 1);
2856                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2857                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2858                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2859                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2860         }
2861
2862         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2863         table->next_idx ++;
2864
2865         return token;
2866 }
2867
2868 /*
2869  * Insert a memberef row into the metadata: the token that point to the memberref
2870  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2871  * mono_image_get_fieldref_token()).
2872  * The sig param is an index to an already built signature.
2873  */
2874 static guint32
2875 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2876 {
2877         MONO_REQ_GC_NEUTRAL_MODE;
2878
2879         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2880         return mono_image_add_memberef_row (assembly, parent, name, sig);
2881 }
2882
2883
2884 static guint32
2885 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2886 {
2887         MONO_REQ_GC_NEUTRAL_MODE;
2888
2889         guint32 token;
2890         MonoMethodSignature *sig;
2891         
2892         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2893
2894         if (create_typespec) {
2895                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2896                 if (token)
2897                         return token;
2898         } 
2899
2900         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2901         if (token && !create_typespec)
2902                 return token;
2903
2904         g_assert (!method->is_inflated);
2905         if (!token) {
2906                 /*
2907                  * A methodref signature can't contain an unmanaged calling convention.
2908                  */
2909                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2910                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2911                         sig->call_convention = MONO_CALL_DEFAULT;
2912                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2913                         method->name,  method_encode_signature (assembly, sig));
2914                 g_free (sig);
2915                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2916         }
2917
2918         if (create_typespec) {
2919                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2920                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2921                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2922
2923                 if (assembly->save) {
2924                         guint32 *values;
2925
2926                         alloc_table (table, table->rows + 1);
2927                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2928                         values [MONO_METHODSPEC_METHOD] = token;
2929                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2930                 }
2931
2932                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2933                 table->next_idx ++;
2934                 /*methodspec and memberef tokens are diferent, */
2935                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2936                 return token;
2937         }
2938         return token;
2939 }
2940
2941 static guint32
2942 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2943 {
2944         guint32 token, parent, sig;
2945         ReflectionMethodBuilder rmb;
2946         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2947         
2948         mono_error_init (error);
2949         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2950         if (token)
2951                 return token;
2952
2953         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2954                 return 0;
2955
2956         /*
2957          * A methodref signature can't contain an unmanaged calling convention.
2958          * Since some flags are encoded as part of call_conv, we need to check against it.
2959         */
2960         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2961                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2962
2963         sig = method_builder_encode_signature (assembly, &rmb, error);
2964         return_val_if_nok (error, 0);
2965
2966         if (tb->generic_params) {
2967                 parent = create_generic_typespec (assembly, tb, error);
2968                 return_val_if_nok (error, 0);
2969         } else {
2970                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2971                 return_val_if_nok (error, 0);
2972
2973                 parent = mono_image_typedef_or_ref (assembly, t);
2974         }
2975
2976         char *name = mono_string_to_utf8 (method->name);
2977
2978         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2979         g_free (name);
2980
2981         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2982
2983         return token;
2984 }
2985
2986 static guint32
2987 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2988                                      const gchar *name, guint32 sig)
2989 {
2990         MonoDynamicTable *table;
2991         guint32 token;
2992         guint32 *values;
2993         
2994         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2995
2996         if (assembly->save) {
2997                 alloc_table (table, table->rows + 1);
2998                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2999                 values [MONO_MEMBERREF_CLASS] = original;
3000                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3001                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3002         }
3003
3004         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3005         table->next_idx ++;
3006
3007         return token;
3008 }
3009
3010 static guint32
3011 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3012 {
3013         SigBuffer buf;
3014         int i;
3015         guint32 nparams = mono_array_length (mb->generic_params);
3016         guint32 idx;
3017
3018         if (!assembly->save)
3019                 return 0;
3020
3021         sigbuffer_init (&buf, 32);
3022
3023         sigbuffer_add_value (&buf, 0xa);
3024         sigbuffer_add_value (&buf, nparams);
3025
3026         for (i = 0; i < nparams; i++) {
3027                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3028                 sigbuffer_add_value (&buf, i);
3029         }
3030
3031         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3032         sigbuffer_free (&buf);
3033         return idx;
3034 }
3035
3036 static guint32
3037 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3038 {
3039         MonoDynamicTable *table;
3040         guint32 *values;
3041         guint32 token, mtoken = 0;
3042
3043         mono_error_init (error);
3044         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3045         if (token)
3046                 return token;
3047
3048         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3049
3050         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3051         if (!mono_error_ok (error))
3052                 return 0;
3053
3054         switch (mono_metadata_token_table (mtoken)) {
3055         case MONO_TABLE_MEMBERREF:
3056                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3057                 break;
3058         case MONO_TABLE_METHOD:
3059                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3060                 break;
3061         default:
3062                 g_assert_not_reached ();
3063         }
3064
3065         if (assembly->save) {
3066                 alloc_table (table, table->rows + 1);
3067                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3068                 values [MONO_METHODSPEC_METHOD] = mtoken;
3069                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3070         }
3071
3072         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3073         table->next_idx ++;
3074
3075         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3076         return token;
3077 }
3078
3079 static guint32
3080 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3081 {
3082         guint32 token;
3083
3084         mono_error_init (error);
3085
3086         if (mb->generic_params && create_methodspec) 
3087                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3088
3089         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3090         if (token)
3091                 return token;
3092
3093         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3094         if (!mono_error_ok (error))
3095                 return 0;
3096         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3097         return token;
3098 }
3099
3100 static guint32
3101 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3102 {
3103         guint32 token, parent, sig;
3104         ReflectionMethodBuilder rmb;
3105         char *name;
3106         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3107         
3108         mono_error_init (error);
3109         
3110         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3111         if (token)
3112                 return token;
3113
3114         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3115                 return 0;
3116
3117         if (tb->generic_params) {
3118                 parent = create_generic_typespec (assembly, tb, error);
3119                 return_val_if_nok (error, 0);
3120         } else {
3121                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3122                 return_val_if_nok (error, 0);
3123                 parent = mono_image_typedef_or_ref (assembly, type);
3124         }
3125         
3126         name = mono_string_to_utf8 (rmb.name);
3127         sig = method_builder_encode_signature (assembly, &rmb, error);
3128         return_val_if_nok (error, 0);
3129
3130         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3131
3132         g_free (name);
3133         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3134         return token;
3135 }
3136 #endif
3137
3138 static gboolean
3139 is_field_on_inst (MonoClassField *field)
3140 {
3141         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3142 }
3143
3144 /*
3145  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3146  */
3147 static MonoType*
3148 get_field_on_inst_generic_type (MonoClassField *field)
3149 {
3150         MonoClass *klass, *gtd;
3151         MonoDynamicGenericClass *dgclass;
3152         int field_index;
3153
3154         g_assert (is_field_on_inst (field));
3155
3156         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3157
3158         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3159                 field_index = field - dgclass->fields;
3160                 return dgclass->field_generic_types [field_index];              
3161         }
3162
3163         klass = field->parent;
3164         gtd = klass->generic_class->container_class;
3165
3166         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3167                 field_index = field - klass->fields;
3168                 return gtd->fields [field_index].type;
3169         }
3170
3171         g_assert_not_reached ();
3172         return 0;
3173 }
3174
3175 #ifndef DISABLE_REFLECTION_EMIT
3176 static guint32
3177 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3178 {
3179         MonoType *type;
3180         guint32 token;
3181
3182         g_assert (field);
3183         g_assert (field->parent);
3184
3185         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3186         if (token)
3187                 return token;
3188
3189         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3190                 int index = field - field->parent->fields;
3191                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3192         } else {
3193                 if (is_field_on_inst (field))
3194                         type = get_field_on_inst_generic_type (field);
3195                 else
3196                         type = mono_field_get_type (field);
3197         }
3198         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3199                                                                                         mono_field_get_name (field),
3200                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3201         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3202         return token;
3203 }
3204
3205 static guint32
3206 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3207 {
3208         guint32 token;
3209         MonoClass *klass;
3210         MonoGenericClass *gclass;
3211         MonoType *type;
3212         char *name;
3213
3214         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3215         if (token)
3216                 return token;
3217         if (is_sre_field_builder (mono_object_class (f->fb))) {
3218                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3219                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3220                 return_val_if_nok (error, 0);
3221                 klass = mono_class_from_mono_type (type);
3222                 gclass = type->data.generic_class;
3223                 g_assert (gclass->is_dynamic);
3224
3225                 guint32 sig_token = field_encode_signature (assembly, fb, error);
3226                 return_val_if_nok (error, 0);
3227                 name = mono_string_to_utf8 (fb->name);
3228                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3229                 g_free (name);          
3230         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3231                 guint32 sig;
3232                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3233
3234                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3235                 return_val_if_nok (error, 0);
3236                 klass = mono_class_from_mono_type (type);
3237
3238                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3239                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3240         } else {
3241                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3242                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3243         }
3244
3245         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3246         return token;
3247 }
3248
3249 static guint32
3250 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3251 {
3252         guint32 sig, token;
3253         MonoClass *klass;
3254         MonoGenericClass *gclass;
3255         MonoType *type;
3256
3257         mono_error_init (error);
3258
3259         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3260
3261         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3262         if (token)
3263                 return token;
3264
3265         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3266                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3267                 ReflectionMethodBuilder rmb;
3268                 char *name;
3269
3270                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3271                 return_val_if_nok (error, 0);
3272                 klass = mono_class_from_mono_type (type);
3273
3274                 gclass = type->data.generic_class;
3275                 g_assert (gclass->is_dynamic);
3276
3277                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3278                         return 0;
3279
3280                 sig = method_builder_encode_signature (assembly, &rmb, error);
3281                 return_val_if_nok (error, 0);
3282
3283                 name = mono_string_to_utf8 (rmb.name);
3284
3285                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3286                 g_free (name);
3287         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3288                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3289
3290                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3291                 return_val_if_nok (error, 0);
3292                 klass = mono_class_from_mono_type (type);
3293
3294                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3295                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3296         } else {
3297                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3298                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3299         }
3300
3301
3302         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3303         return token;
3304 }
3305
3306 static MonoMethod*
3307 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3308 {
3309         MonoClass *klass;
3310         MonoGenericContext tmp_context;
3311         MonoType **type_argv;
3312         MonoGenericInst *ginst;
3313         MonoMethod *method, *inflated;
3314         int count, i;
3315
3316         mono_error_init (error);
3317
3318         init_type_builder_generics ((MonoObject*)m->inst);
3319
3320         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3321         return_val_if_nok (error, NULL);
3322
3323         klass = method->klass;
3324
3325         if (m->method_args == NULL)
3326                 return method;
3327
3328         if (method->is_inflated)
3329                 method = ((MonoMethodInflated *) method)->declaring;
3330
3331         count = mono_array_length (m->method_args);
3332
3333         type_argv = g_new0 (MonoType *, count);
3334         for (i = 0; i < count; i++) {
3335                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3336                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3337                 return_val_if_nok (error, NULL);
3338         }
3339         ginst = mono_metadata_get_generic_inst (count, type_argv);
3340         g_free (type_argv);
3341
3342         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3343         tmp_context.method_inst = ginst;
3344
3345         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3346         mono_error_assert_ok (error);
3347         return inflated;
3348 }
3349
3350 static guint32
3351 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3352 {
3353         guint32 sig, token = 0;
3354         MonoType *type;
3355         MonoClass *klass;
3356
3357         mono_error_init (error);
3358
3359         if (m->method_args) {
3360                 MonoMethod *inflated;
3361
3362                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3363                 return_val_if_nok (error, 0);
3364
3365                 if (create_methodspec)
3366                         token = mono_image_get_methodspec_token (assembly, inflated);
3367                 else
3368                         token = mono_image_get_inflated_method_token (assembly, inflated);
3369                 return token;
3370         }
3371
3372         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3373         if (token)
3374                 return token;
3375
3376         if (is_sre_method_builder (mono_object_class (m->mb))) {
3377                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3378                 MonoGenericClass *gclass;
3379                 ReflectionMethodBuilder rmb;
3380                 char *name;
3381
3382                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3383                 return_val_if_nok (error, 0);
3384                 klass = mono_class_from_mono_type (type);
3385                 gclass = type->data.generic_class;
3386                 g_assert (gclass->is_dynamic);
3387
3388                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3389                         return 0;
3390
3391                 sig = method_builder_encode_signature (assembly, &rmb, error);
3392                 return_val_if_nok (error, 0);
3393
3394                 name = mono_string_to_utf8 (rmb.name);
3395
3396                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3397                 g_free (name);          
3398         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3399                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3400
3401                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3402                 return_val_if_nok (error, 0);
3403                 klass = mono_class_from_mono_type (type);
3404
3405                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3406                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3407         } else {
3408                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3409                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3410         }
3411
3412         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3413         return token;
3414 }
3415
3416 static guint32
3417 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3418 {
3419         SigBuffer buf;
3420         int i;
3421         guint32 nparams = context->method_inst->type_argc;
3422         guint32 idx;
3423
3424         if (!assembly->save)
3425                 return 0;
3426
3427         sigbuffer_init (&buf, 32);
3428         /*
3429          * FIXME: vararg, explicit_this, differenc call_conv values...
3430          */
3431         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3432         sigbuffer_add_value (&buf, nparams);
3433
3434         for (i = 0; i < nparams; i++)
3435                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3436
3437         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3438         sigbuffer_free (&buf);
3439         return idx;
3440 }
3441
3442 static guint32
3443 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3444 {
3445         MonoDynamicTable *table;
3446         guint32 *values;
3447         guint32 token, mtoken = 0, sig;
3448         MonoMethodInflated *imethod;
3449         MonoMethod *declaring;
3450
3451         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3452
3453         g_assert (method->is_inflated);
3454         imethod = (MonoMethodInflated *) method;
3455         declaring = imethod->declaring;
3456
3457         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3458         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3459
3460         if (!mono_method_signature (declaring)->generic_param_count)
3461                 return mtoken;
3462
3463         switch (mono_metadata_token_table (mtoken)) {
3464         case MONO_TABLE_MEMBERREF:
3465                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3466                 break;
3467         case MONO_TABLE_METHOD:
3468                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3469                 break;
3470         default:
3471                 g_assert_not_reached ();
3472         }
3473
3474         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3475
3476         if (assembly->save) {
3477                 alloc_table (table, table->rows + 1);
3478                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3479                 values [MONO_METHODSPEC_METHOD] = mtoken;
3480                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3481         }
3482
3483         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3484         table->next_idx ++;
3485
3486         return token;
3487 }
3488
3489 static guint32
3490 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3491 {
3492         MonoMethodInflated *imethod;
3493         guint32 token;
3494         
3495         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3496         if (token)
3497                 return token;
3498
3499         g_assert (method->is_inflated);
3500         imethod = (MonoMethodInflated *) method;
3501
3502         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3503                 token = method_encode_methodspec (assembly, method);
3504         } else {
3505                 guint32 sig = method_encode_signature (
3506                         assembly, mono_method_signature (imethod->declaring));
3507                 token = mono_image_get_memberref_token (
3508                         assembly, &method->klass->byval_arg, method->name, sig);
3509         }
3510
3511         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3512         return token;
3513 }
3514
3515 static guint32
3516 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3517 {
3518         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3519         guint32 sig, token;
3520
3521         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3522         token = mono_image_get_memberref_token (
3523                 assembly, &m->klass->byval_arg, m->name, sig);
3524
3525         return token;
3526 }
3527
3528 static guint32
3529 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3530 {
3531         MonoDynamicTable *table;
3532         MonoClass *klass;
3533         MonoType *type;
3534         guint32 *values;
3535         guint32 token;
3536         SigBuffer buf;
3537         int count, i;
3538
3539         /*
3540          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3541          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3542          * Because of this, we must not insert it into the `typeref' hash table.
3543          */
3544         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3545         return_val_if_nok (error, 0);
3546         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3547         if (token)
3548                 return token;
3549
3550         sigbuffer_init (&buf, 32);
3551
3552         g_assert (tb->generic_params);
3553         klass = mono_class_from_mono_type (type);
3554
3555         if (tb->generic_container)
3556                 mono_reflection_create_generic_class (tb);
3557
3558         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3559         g_assert (klass->generic_container);
3560         sigbuffer_add_value (&buf, klass->byval_arg.type);
3561         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3562
3563         count = mono_array_length (tb->generic_params);
3564         sigbuffer_add_value (&buf, count);
3565         for (i = 0; i < count; i++) {
3566                 MonoReflectionGenericParam *gparam;
3567
3568                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3569                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3570                 if (!is_ok (error))
3571                         goto fail;
3572
3573                 encode_type (assembly, gparam_type, &buf);
3574         }
3575
3576         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3577
3578         if (assembly->save) {
3579                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3580                 alloc_table (table, table->rows + 1);
3581                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3582                 values [MONO_TYPESPEC_SIGNATURE] = token;
3583         }
3584         sigbuffer_free (&buf);
3585
3586         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3587         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3588         table->next_idx ++;
3589         return token;
3590 fail:
3591         sigbuffer_free (&buf);
3592         return 0;
3593 }
3594
3595 /*
3596  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3597  */
3598 static MonoType*
3599 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3600 {
3601         int i, count, len, pos;
3602         MonoType *t;
3603
3604         mono_error_init (error);
3605
3606         count = 0;
3607         if (modreq)
3608                 count += mono_array_length (modreq);
3609         if (modopt)
3610                 count += mono_array_length (modopt);
3611
3612         if (count == 0)
3613                 return mono_metadata_type_dup (NULL, type);
3614
3615         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3616         t = (MonoType *)g_malloc (len);
3617         memcpy (t, type, MONO_SIZEOF_TYPE);
3618
3619         t->num_mods = count;
3620         pos = 0;
3621         if (modreq) {
3622                 for (i = 0; i < mono_array_length (modreq); ++i) {
3623                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3624                         if (!is_ok (error))
3625                                 goto fail;
3626                         t->modifiers [pos].required = 1;
3627                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3628                         pos ++;
3629                 }
3630         }
3631         if (modopt) {
3632                 for (i = 0; i < mono_array_length (modopt); ++i) {
3633                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3634                         if (!is_ok (error))
3635                                 goto fail;
3636                         t->modifiers [pos].required = 0;
3637                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3638                         pos ++;
3639                 }
3640         }
3641
3642         return t;
3643 fail:
3644         g_free (t);
3645         return NULL;
3646 }
3647
3648 static void
3649 init_type_builder_generics (MonoObject *type)
3650 {
3651         MonoReflectionTypeBuilder *tb;
3652
3653         if (!is_sre_type_builder(mono_object_class (type)))
3654                 return;
3655         tb = (MonoReflectionTypeBuilder *)type;
3656
3657         if (tb && tb->generic_container)
3658                 mono_reflection_create_generic_class (tb);
3659 }
3660
3661 static guint32
3662 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3663 {
3664         MonoDynamicTable *table;
3665         MonoType *custom = NULL, *type;
3666         guint32 *values;
3667         guint32 token, pclass, parent, sig;
3668         gchar *name;
3669
3670         mono_error_init (error);
3671
3672         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3673         if (token)
3674                 return token;
3675
3676         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3677         return_val_if_nok (error, 0);
3678         /* FIXME: is this call necessary? */
3679         mono_class_from_mono_type (typeb);
3680
3681         /*FIXME this is one more layer of ugliness due how types are created.*/
3682         init_type_builder_generics (fb->type);
3683
3684         /* fb->type does not include the custom modifiers */
3685         /* FIXME: We should do this in one place when a fieldbuilder is created */
3686         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3687         return_val_if_nok (error, 0);
3688
3689         if (fb->modreq || fb->modopt) {
3690                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3691                 return_val_if_nok (error, 0);
3692         }
3693
3694         sig = fieldref_encode_signature (assembly, NULL, type);
3695         g_free (custom);
3696
3697         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3698         return_val_if_nok (error, 0);
3699         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3700         
3701         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3702         parent >>= MONO_TYPEDEFORREF_BITS;
3703
3704         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3705
3706         name = mono_string_to_utf8 (fb->name);
3707
3708         if (assembly->save) {
3709                 alloc_table (table, table->rows + 1);
3710                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3711                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3712                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3713                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3714         }
3715
3716         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3717         table->next_idx ++;
3718         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3719         g_free (name);
3720         return token;
3721 }
3722
3723 static guint32
3724 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3725 {
3726         SigBuffer buf;
3727         guint32 nargs;
3728         guint32 i, idx;
3729
3730         mono_error_init (error);
3731
3732         if (!assembly->save)
3733                 return 0;
3734
3735         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3736         g_assert (helper->type == 2);
3737
3738         if (helper->arguments)
3739                 nargs = mono_array_length (helper->arguments);
3740         else
3741                 nargs = 0;
3742
3743         sigbuffer_init (&buf, 32);
3744
3745         /* Encode calling convention */
3746         /* Change Any to Standard */
3747         if ((helper->call_conv & 0x03) == 0x03)
3748                 helper->call_conv = 0x01;
3749         /* explicit_this implies has_this */
3750         if (helper->call_conv & 0x40)
3751                 helper->call_conv &= 0x20;
3752
3753         if (helper->call_conv == 0) { /* Unmanaged */
3754                 idx = helper->unmanaged_call_conv - 1;
3755         } else {
3756                 /* Managed */
3757                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3758                 if (helper->call_conv & 0x02) /* varargs */
3759                         idx += 0x05;
3760         }
3761
3762         sigbuffer_add_byte (&buf, idx);
3763         sigbuffer_add_value (&buf, nargs);
3764         encode_reflection_type (assembly, helper->return_type, &buf, error);
3765         if (!is_ok (error))
3766                 goto fail;
3767         for (i = 0; i < nargs; ++i) {
3768                 MonoArray *modreqs = NULL;
3769                 MonoArray *modopts = NULL;
3770                 MonoReflectionType *pt;
3771
3772                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3773                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3774                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3775                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3776
3777                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3778                 if (!is_ok (error))
3779                         goto fail;
3780                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3781                 encode_reflection_type (assembly, pt, &buf, error);
3782                 if (!is_ok (error))
3783                         goto fail;
3784         }
3785         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3786         sigbuffer_free (&buf);
3787
3788         return idx;
3789 fail:
3790         sigbuffer_free (&buf);
3791         return 0;
3792 }
3793
3794 static guint32 
3795 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3796 {
3797         guint32 idx;
3798         MonoDynamicTable *table;
3799         guint32 *values;
3800
3801         mono_error_init (error);
3802
3803         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3804         idx = table->next_idx ++;
3805         table->rows ++;
3806         alloc_table (table, table->rows);
3807         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3808
3809         values [MONO_STAND_ALONE_SIGNATURE] =
3810                 mono_reflection_encode_sighelper (assembly, helper, error);
3811         return_val_if_nok (error, 0);
3812         
3813         return idx;
3814 }
3815
3816 static int
3817 reflection_cc_to_file (int call_conv) {
3818         switch (call_conv & 0x3) {
3819         case 0:
3820         case 1: return MONO_CALL_DEFAULT;
3821         case 2: return MONO_CALL_VARARG;
3822         default:
3823                 g_assert_not_reached ();
3824         }
3825         return 0;
3826 }
3827 #endif /* !DISABLE_REFLECTION_EMIT */
3828
3829 typedef struct {
3830         MonoType *parent;
3831         MonoMethodSignature *sig;
3832         char *name;
3833         guint32 token;
3834 } ArrayMethod;
3835
3836 #ifndef DISABLE_REFLECTION_EMIT
3837 static guint32
3838 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3839 {
3840         guint32 nparams, i;
3841         GList *tmp;
3842         char *name = NULL;
3843         MonoMethodSignature *sig;
3844         ArrayMethod *am = NULL;
3845         MonoType *mtype;
3846
3847         mono_error_init (error);
3848
3849         nparams = mono_array_length (m->parameters);
3850         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3851         sig->hasthis = 1;
3852         sig->sentinelpos = -1;
3853         sig->call_convention = reflection_cc_to_file (m->call_conv);
3854         sig->param_count = nparams;
3855         if (m->ret) {
3856                 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3857                 if (!is_ok (error))
3858                         goto fail;
3859         } else
3860                 sig->ret = &mono_defaults.void_class->byval_arg;
3861
3862         mtype = mono_reflection_type_get_handle (m->parent, error);
3863         if (!is_ok (error))
3864                 goto fail;
3865
3866         for (i = 0; i < nparams; ++i) {
3867                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3868                 if (!is_ok (error))
3869                         goto fail;
3870         }
3871
3872         name = mono_string_to_utf8 (m->name);
3873         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3874                 am = (ArrayMethod *)tmp->data;
3875                 if (strcmp (name, am->name) == 0 && 
3876                                 mono_metadata_type_equal (am->parent, mtype) &&
3877                                 mono_metadata_signature_equal (am->sig, sig)) {
3878                         g_free (name);
3879                         g_free (sig);
3880                         m->table_idx = am->token & 0xffffff;
3881                         return am->token;
3882                 }
3883         }
3884         am = g_new0 (ArrayMethod, 1);
3885         am->name = name;
3886         am->sig = sig;
3887         am->parent = mtype;
3888         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3889                 method_encode_signature (assembly, sig));
3890         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3891         m->table_idx = am->token & 0xffffff;
3892         return am->token;
3893 fail:
3894         g_free (am);
3895         g_free (name);
3896         g_free (sig);
3897         return 0;
3898
3899 }
3900
3901 /*
3902  * Insert into the metadata tables all the info about the TypeBuilder tb.
3903  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3904  */
3905 static gboolean
3906 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3907 {
3908         MonoDynamicTable *table;
3909         guint *values;
3910         int i, is_object = 0, is_system = 0;
3911         char *n;
3912
3913         mono_error_init (error);
3914
3915         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3916         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3917         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3918         n = mono_string_to_utf8 (tb->name);
3919         if (strcmp (n, "Object") == 0)
3920                 is_object++;
3921         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3922         g_free (n);
3923         n = mono_string_to_utf8 (tb->nspace);
3924         if (strcmp (n, "System") == 0)
3925                 is_system++;
3926         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3927         g_free (n);
3928         if (tb->parent && !(is_system && is_object) && 
3929                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3930                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3931                 return_val_if_nok (error, FALSE);
3932                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3933         } else {
3934                 values [MONO_TYPEDEF_EXTENDS] = 0;
3935         }
3936         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3937         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3938
3939         /*
3940          * if we have explicitlayout or sequentiallayouts, output data in the
3941          * ClassLayout table.
3942          */
3943         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3944                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3945                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3946                 table->rows++;
3947                 alloc_table (table, table->rows);
3948                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3949                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3950                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3951                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3952         }
3953
3954         /* handle interfaces */
3955         if (tb->interfaces) {
3956                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3957                 i = table->rows;
3958                 table->rows += mono_array_length (tb->interfaces);
3959                 alloc_table (table, table->rows);
3960                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3961                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3962                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3963                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3964                         return_val_if_nok (error, FALSE);
3965                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3966                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3967                         values += MONO_INTERFACEIMPL_SIZE;
3968                 }
3969         }
3970
3971         /* handle fields */
3972         if (tb->fields) {
3973                 table = &assembly->tables [MONO_TABLE_FIELD];
3974                 table->rows += tb->num_fields;
3975                 alloc_table (table, table->rows);
3976                 for (i = 0; i < tb->num_fields; ++i) {
3977                         mono_image_get_field_info (
3978                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3979                         return_val_if_nok (error, FALSE);
3980                 }
3981         }
3982
3983         /* handle constructors */
3984         if (tb->ctors) {
3985                 table = &assembly->tables [MONO_TABLE_METHOD];
3986                 table->rows += mono_array_length (tb->ctors);
3987                 alloc_table (table, table->rows);
3988                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3989                         if (!mono_image_get_ctor_info (domain,
3990                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3991                                                        assembly, error))
3992                                 return FALSE;
3993                 }
3994         }
3995
3996         /* handle methods */
3997         if (tb->methods) {
3998                 table = &assembly->tables [MONO_TABLE_METHOD];
3999                 table->rows += tb->num_methods;
4000                 alloc_table (table, table->rows);
4001                 for (i = 0; i < tb->num_methods; ++i) {
4002                         if (!mono_image_get_method_info (
4003                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4004                                 return FALSE;
4005                 }
4006         }
4007
4008         /* Do the same with properties etc.. */
4009         if (tb->events && mono_array_length (tb->events)) {
4010                 table = &assembly->tables [MONO_TABLE_EVENT];
4011                 table->rows += mono_array_length (tb->events);
4012                 alloc_table (table, table->rows);
4013                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4014                 table->rows ++;
4015                 alloc_table (table, table->rows);
4016                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4017                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4018                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4019                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4020                         mono_image_get_event_info (
4021                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4022                         return_val_if_nok (error, FALSE);
4023                 }
4024         }
4025         if (tb->properties && mono_array_length (tb->properties)) {
4026                 table = &assembly->tables [MONO_TABLE_PROPERTY];
4027                 table->rows += mono_array_length (tb->properties);
4028                 alloc_table (table, table->rows);
4029                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4030                 table->rows ++;
4031                 alloc_table (table, table->rows);
4032                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4033                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4034                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4035                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4036                         mono_image_get_property_info (
4037                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4038                         return_val_if_nok (error, FALSE);
4039                 }
4040         }
4041
4042         /* handle generic parameters */
4043         if (tb->generic_params) {
4044                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4045                 table->rows += mono_array_length (tb->generic_params);
4046                 alloc_table (table, table->rows);
4047                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4048                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4049
4050                         mono_image_get_generic_param_info (
4051                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4052                 }
4053         }
4054
4055         mono_image_add_decl_security (assembly, 
4056                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4057
4058         if (tb->subtypes) {
4059                 MonoDynamicTable *ntable;
4060                 
4061                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4062                 ntable->rows += mono_array_length (tb->subtypes);
4063                 alloc_table (ntable, ntable->rows);
4064                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4065
4066                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4067                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4068
4069                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4070                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4071                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4072                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4073                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4074                                 ntable->next_idx, ntable->rows);*/
4075                         values += MONO_NESTED_CLASS_SIZE;
4076                         ntable->next_idx++;
4077                 }
4078         }
4079
4080         return TRUE;
4081 }
4082 #endif
4083
4084 static void
4085 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4086 {
4087         int i;
4088
4089         mono_ptr_array_append (*types, type);
4090
4091         if (!type->subtypes)
4092                 return;
4093
4094         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4095                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4096                 collect_types (types, subtype);
4097         }
4098 }
4099
4100 static gint
4101 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4102 {
4103         if ((*type1)->table_idx < (*type2)->table_idx)
4104                 return -1;
4105         else
4106                 if ((*type1)->table_idx > (*type2)->table_idx)
4107                         return 1;
4108         else
4109                 return 0;
4110 }
4111
4112 static gboolean
4113 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4114         int i;
4115
4116         mono_error_init (error);
4117         if (!pinfo)
4118                 return TRUE;
4119         for (i = 0; i < mono_array_length (pinfo); ++i) {
4120                 MonoReflectionParamBuilder *pb;
4121                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4122                 if (!pb)
4123                         continue;
4124                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4125                         return FALSE;
4126         }
4127
4128         return TRUE;
4129 }
4130
4131 static gboolean
4132 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4133         int i;
4134
4135         mono_error_init (error);
4136         
4137         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4138                 return FALSE;
4139         if (tb->fields) {
4140                 for (i = 0; i < tb->num_fields; ++i) {
4141                         MonoReflectionFieldBuilder* fb;
4142                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4143                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4144                                 return FALSE;
4145                 }
4146         }
4147         if (tb->events) {
4148                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4149                         MonoReflectionEventBuilder* eb;
4150                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4151                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4152                                 return FALSE;
4153                 }
4154         }
4155         if (tb->properties) {
4156                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4157                         MonoReflectionPropertyBuilder* pb;
4158                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4159                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4160                                 return FALSE;
4161                 }
4162         }
4163         if (tb->ctors) {
4164                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4165                         MonoReflectionCtorBuilder* cb;
4166                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4167                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4168                             !params_add_cattrs (assembly, cb->pinfo, error))
4169                                 return FALSE;
4170                 }
4171         }
4172
4173         if (tb->methods) {
4174                 for (i = 0; i < tb->num_methods; ++i) {
4175                         MonoReflectionMethodBuilder* mb;
4176                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4177                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4178                             !params_add_cattrs (assembly, mb->pinfo, error))
4179                                 return FALSE;
4180                 }
4181         }
4182
4183         if (tb->subtypes) {
4184                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4185                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4186                                 return FALSE;
4187                 }
4188         }
4189
4190         return TRUE;
4191 }
4192
4193 static gboolean
4194 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4195 {
4196         int i;
4197         
4198         mono_error_init (error);
4199
4200         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4201                 return FALSE;
4202
4203         if (moduleb->global_methods) {
4204                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4205                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4206                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4207                             !params_add_cattrs (assembly, mb->pinfo, error))
4208                                 return FALSE;
4209                 }
4210         }
4211
4212         if (moduleb->global_fields) {
4213                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4214                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4215                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4216                                 return FALSE;
4217                 }
4218         }
4219         
4220         if (moduleb->types) {
4221                 for (i = 0; i < moduleb->num_types; ++i) {
4222                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4223                                 return FALSE;
4224                 }
4225         }
4226
4227         return TRUE;
4228 }
4229
4230 static void
4231 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4232 {
4233         MonoDynamicTable *table;
4234         guint32 *values;
4235         char blob_size [6];
4236         guchar hash [20];
4237         char *b = blob_size;
4238         char *dir, *path;
4239
4240         table = &assembly->tables [MONO_TABLE_FILE];
4241         table->rows++;
4242         alloc_table (table, table->rows);
4243         values = table->values + table->next_idx * MONO_FILE_SIZE;
4244         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4245         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4246         if (image_is_dynamic (module->image)) {
4247                 /* This depends on the fact that the main module is emitted last */
4248                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4249                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4250         } else {
4251                 dir = NULL;
4252                 path = g_strdup (module->image->name);
4253         }
4254         mono_sha1_get_digest_from_file (path, hash);
4255         g_free (dir);
4256         g_free (path);
4257         mono_metadata_encode_value (20, b, &b);
4258         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4259         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4260         table->next_idx ++;
4261 }
4262
4263 static void
4264 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4265 {
4266         MonoDynamicTable *table;
4267         int i;
4268
4269         table = &assembly->tables [MONO_TABLE_MODULE];
4270         mb->table_idx = table->next_idx ++;
4271         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4272         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4273         i /= 16;
4274         ++i;
4275         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4276         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4277         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4278         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4279 }
4280
4281 static guint32
4282 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4283         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4284 {
4285         MonoDynamicTable *table;
4286         guint32 *values;
4287         guint32 visib, res;
4288
4289         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4290         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4291                 return 0;
4292
4293         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4294         table->rows++;
4295         alloc_table (table, table->rows);
4296         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4297
4298         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4299         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4300         if (klass->nested_in)
4301                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4302         else
4303                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4304         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4305         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4306
4307         res = table->next_idx;
4308
4309         table->next_idx ++;
4310
4311         /* Emit nested types */
4312         if (klass->ext && klass->ext->nested_classes) {
4313                 GList *tmp;
4314
4315                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4316                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4317         }
4318
4319         return res;
4320 }
4321
4322 static void
4323 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4324                               guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4325                               MonoError *error)
4326 {
4327         MonoClass *klass;
4328         guint32 idx, i;
4329
4330         mono_error_init (error);
4331
4332         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4333         return_if_nok (error);
4334
4335         klass = mono_class_from_mono_type (t);
4336
4337         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4338
4339         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4340                                                                                                    parent_index, assembly);
4341
4342         /* 
4343          * Emit nested types
4344          * We need to do this ourselves since klass->nested_classes is not set up.
4345          */
4346         if (tb->subtypes) {
4347                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4348                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4349                         return_if_nok (error);
4350                 }
4351         }
4352 }
4353
4354 static void
4355 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4356         guint32 module_index, MonoDynamicImage *assembly)
4357 {
4358         MonoImage *image = module->image;
4359         MonoTableInfo  *t;
4360         guint32 i;
4361
4362         t = &image->tables [MONO_TABLE_TYPEDEF];
4363
4364         for (i = 0; i < t->rows; ++i) {
4365                 MonoError error;
4366                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4367                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4368
4369                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4370                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4371         }
4372 }
4373
4374 static void
4375 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4376 {
4377         MonoDynamicTable *table;
4378         guint32 *values;
4379         guint32 scope, scope_idx, impl, current_idx;
4380         gboolean forwarder = TRUE;
4381         gpointer iter = NULL;
4382         MonoClass *nested;
4383
4384         if (klass->nested_in) {
4385                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4386                 forwarder = FALSE;
4387         } else {
4388                 scope = resolution_scope_from_image (assembly, klass->image);
4389                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4390                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4391                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4392         }
4393
4394         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4395
4396         table->rows++;
4397         alloc_table (table, table->rows);
4398         current_idx = table->next_idx;
4399         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4400
4401         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4402         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4403         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4404         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4405         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4406
4407         table->next_idx++;
4408
4409         while ((nested = mono_class_get_nested_types (klass, &iter)))
4410                 add_exported_type (assemblyb, assembly, nested, current_idx);
4411 }
4412
4413 static void
4414 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4415 {
4416         MonoError error;
4417         MonoClass *klass;
4418         int i;
4419
4420         if (!assemblyb->type_forwarders)
4421                 return;
4422
4423         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4424                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4425                 MonoType *type;
4426                 if (!t)
4427                         continue;
4428
4429                 type = mono_reflection_type_get_handle (t, &error);
4430                 mono_error_assert_ok (&error);
4431                 g_assert (type);
4432
4433                 klass = mono_class_from_mono_type (type);
4434
4435                 add_exported_type (assemblyb, assembly, klass, 0);
4436         }
4437 }
4438
4439 #define align_pointer(base,p)\
4440         do {\
4441                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4442                 if (__diff & 3)\
4443                         (p) += 4 - (__diff & 3);\
4444         } while (0)
4445
4446 static int
4447 compare_constants (const void *a, const void *b)
4448 {
4449         const guint32 *a_values = (const guint32 *)a;
4450         const guint32 *b_values = (const guint32 *)b;
4451         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4452 }
4453
4454 static int
4455 compare_semantics (const void *a, const void *b)
4456 {
4457         const guint32 *a_values = (const guint32 *)a;
4458         const guint32 *b_values = (const guint32 *)b;
4459         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4460         if (assoc)
4461                 return assoc;
4462         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4463 }
4464
4465 static int
4466 compare_custom_attrs (const void *a, const void *b)
4467 {
4468         const guint32 *a_values = (const guint32 *)a;
4469         const guint32 *b_values = (const guint32 *)b;
4470
4471         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4472 }
4473
4474 static int
4475 compare_field_marshal (const void *a, const void *b)
4476 {
4477         const guint32 *a_values = (const guint32 *)a;
4478         const guint32 *b_values = (const guint32 *)b;
4479
4480         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4481 }
4482
4483 static int
4484 compare_nested (const void *a, const void *b)
4485 {
4486         const guint32 *a_values = (const guint32 *)a;
4487         const guint32 *b_values = (const guint32 *)b;
4488
4489         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4490 }
4491
4492 static int
4493 compare_genericparam (const void *a, const void *b)
4494 {
4495         MonoError error;
4496         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4497         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4498
4499         if ((*b_entry)->owner == (*a_entry)->owner) {
4500                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4501                 mono_error_assert_ok (&error);
4502                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4503                 mono_error_assert_ok (&error);
4504                 return 
4505                         mono_type_get_generic_param_num (a_type) -
4506                         mono_type_get_generic_param_num (b_type);
4507         } else
4508                 return (*a_entry)->owner - (*b_entry)->owner;
4509 }
4510
4511 static int
4512 compare_declsecurity_attrs (const void *a, const void *b)
4513 {
4514         const guint32 *a_values = (const guint32 *)a;
4515         const guint32 *b_values = (const guint32 *)b;
4516
4517         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4518 }
4519
4520 static int
4521 compare_interface_impl (const void *a, const void *b)
4522 {
4523         const guint32 *a_values = (const guint32 *)a;
4524         const guint32 *b_values = (const guint32 *)b;
4525
4526         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4527         if (klass)
4528                 return klass;
4529
4530         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4531 }
4532
4533 static void
4534 pad_heap (MonoDynamicStream *sh)
4535 {
4536         if (sh->index & 3) {
4537                 int sz = 4 - (sh->index & 3);
4538                 memset (sh->data + sh->index, 0, sz);
4539                 sh->index += sz;
4540         }
4541 }
4542
4543 struct StreamDesc {
4544         const char *name;
4545         MonoDynamicStream *stream;
4546 };
4547
4548 /*
4549  * build_compressed_metadata() fills in the blob of data that represents the 
4550  * raw metadata as it will be saved in the PE file. The five streams are output 
4551  * and the metadata tables are comnpressed from the guint32 array representation, 
4552  * to the compressed on-disk format.
4553  */
4554 static gboolean
4555 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4556 {
4557         MonoDynamicTable *table;
4558         int i;
4559         guint64 valid_mask = 0;
4560         guint64 sorted_mask;
4561         guint32 heapt_size = 0;
4562         guint32 meta_size = 256; /* allow for header and other stuff */
4563         guint32 table_offset;
4564         guint32 ntables = 0;
4565         guint64 *int64val;
4566         guint32 *int32val;
4567         guint16 *int16val;
4568         MonoImage *meta;
4569         unsigned char *p;
4570         struct StreamDesc stream_desc [5];
4571
4572         mono_error_init (error);
4573
4574         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4575         for (i = 0; i < assembly->gen_params->len; i++) {
4576                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4577                 if (!write_generic_param_entry (assembly, entry, error))
4578                         return FALSE;
4579         }
4580
4581         stream_desc [0].name  = "#~";
4582         stream_desc [0].stream = &assembly->tstream;
4583         stream_desc [1].name  = "#Strings";
4584         stream_desc [1].stream = &assembly->sheap;
4585         stream_desc [2].name  = "#US";
4586         stream_desc [2].stream = &assembly->us;
4587         stream_desc [3].name  = "#Blob";
4588         stream_desc [3].stream = &assembly->blob;
4589         stream_desc [4].name  = "#GUID";
4590         stream_desc [4].stream = &assembly->guid;
4591         
4592         /* tables that are sorted */
4593         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4594                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4595                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4596                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4597                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4598                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4599                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4600         
4601         /* Compute table sizes */
4602         /* the MonoImage has already been created in mono_image_basic_init() */
4603         meta = &assembly->image;
4604
4605         /* sizes should be multiple of 4 */
4606         pad_heap (&assembly->blob);
4607         pad_heap (&assembly->guid);
4608         pad_heap (&assembly->sheap);
4609         pad_heap (&assembly->us);
4610
4611         /* Setup the info used by compute_sizes () */
4612         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4613         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4614         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4615
4616         meta_size += assembly->blob.index;
4617         meta_size += assembly->guid.index;
4618         meta_size += assembly->sheap.index;
4619         meta_size += assembly->us.index;
4620
4621         for (i=0; i < MONO_TABLE_NUM; ++i)
4622                 meta->tables [i].rows = assembly->tables [i].rows;
4623         
4624         for (i = 0; i < MONO_TABLE_NUM; i++){
4625                 if (meta->tables [i].rows == 0)
4626                         continue;
4627                 valid_mask |= (guint64)1 << i;
4628                 ntables ++;
4629                 meta->tables [i].row_size = mono_metadata_compute_size (
4630                         meta, i, &meta->tables [i].size_bitfield);
4631                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4632         }
4633         heapt_size += 24; /* #~ header size */
4634         heapt_size += ntables * 4;
4635         /* make multiple of 4 */
4636         heapt_size += 3;
4637         heapt_size &= ~3;
4638         meta_size += heapt_size;
4639         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4640         p = (unsigned char*)meta->raw_metadata;
4641         /* the metadata signature */
4642         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4643         /* version numbers and 4 bytes reserved */
4644         int16val = (guint16*)p;
4645         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4646         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4647         p += 8;
4648         /* version string */
4649         int32val = (guint32*)p;
4650         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4651         p += 4;
4652         memcpy (p, meta->version, strlen (meta->version));
4653         p += GUINT32_FROM_LE (*int32val);
4654         align_pointer (meta->raw_metadata, p);
4655         int16val = (guint16*)p;
4656         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4657         *int16val = GUINT16_TO_LE (5); /* number of streams */
4658         p += 4;
4659
4660         /*
4661          * write the stream info.
4662          */
4663         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4664         table_offset += 3; table_offset &= ~3;
4665
4666         assembly->tstream.index = heapt_size;
4667         for (i = 0; i < 5; ++i) {
4668                 int32val = (guint32*)p;
4669                 stream_desc [i].stream->offset = table_offset;
4670                 *int32val++ = GUINT32_TO_LE (table_offset);
4671                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4672                 table_offset += GUINT32_FROM_LE (*int32val);
4673                 table_offset += 3; table_offset &= ~3;
4674                 p += 8;
4675                 strcpy ((char*)p, stream_desc [i].name);
4676                 p += strlen (stream_desc [i].name) + 1;
4677                 align_pointer (meta->raw_metadata, p);
4678         }
4679         /* 
4680          * now copy the data, the table stream header and contents goes first.
4681          */
4682         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4683         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4684         int32val = (guint32*)p;
4685         *int32val = GUINT32_TO_LE (0); /* reserved */
4686         p += 4;
4687
4688         *p++ = 2; /* version */
4689         *p++ = 0;
4690
4691         if (meta->idx_string_wide)
4692                 *p |= 0x01;
4693         if (meta->idx_guid_wide)
4694                 *p |= 0x02;
4695         if (meta->idx_blob_wide)
4696                 *p |= 0x04;
4697         ++p;
4698         *p++ = 1; /* reserved */
4699         int64val = (guint64*)p;
4700         *int64val++ = GUINT64_TO_LE (valid_mask);
4701         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4702         p += 16;
4703         int32val = (guint32*)p;
4704         for (i = 0; i < MONO_TABLE_NUM; i++){
4705                 if (meta->tables [i].rows == 0)
4706                         continue;
4707                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4708         }
4709         p = (unsigned char*)int32val;
4710
4711         /* sort the tables that still need sorting */
4712         table = &assembly->tables [MONO_TABLE_CONSTANT];
4713         if (table->rows)
4714                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4715         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4716         if (table->rows)
4717                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4718         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4719         if (table->rows)
4720                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4721         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4722         if (table->rows)
4723                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4724         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4725         if (table->rows)
4726                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4727         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4728         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4729         if (table->rows)
4730                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4731         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4732         if (table->rows)
4733                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4734
4735         /* compress the tables */
4736         for (i = 0; i < MONO_TABLE_NUM; i++){
4737                 int row, col;
4738                 guint32 *values;
4739                 guint32 bitfield = meta->tables [i].size_bitfield;
4740                 if (!meta->tables [i].rows)
4741                         continue;
4742                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4743                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4744                 meta->tables [i].base = (char*)p;
4745                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4746                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4747                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4748                                 switch (mono_metadata_table_size (bitfield, col)) {
4749                                 case 1:
4750                                         *p++ = values [col];
4751                                         break;
4752                                 case 2:
4753                                         *p++ = values [col] & 0xff;
4754                                         *p++ = (values [col] >> 8) & 0xff;
4755                                         break;
4756                                 case 4:
4757                                         *p++ = values [col] & 0xff;
4758                                         *p++ = (values [col] >> 8) & 0xff;
4759                                         *p++ = (values [col] >> 16) & 0xff;
4760                                         *p++ = (values [col] >> 24) & 0xff;
4761                                         break;
4762                                 default:
4763                                         g_assert_not_reached ();
4764                                 }
4765                         }
4766                 }
4767                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4768         }
4769         
4770         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4771         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4772         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4773         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4774         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4775
4776         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4777
4778         return TRUE;
4779 }
4780
4781 /*
4782  * Some tables in metadata need to be sorted according to some criteria, but
4783  * when methods and fields are first created with reflection, they may be assigned a token
4784  * that doesn't correspond to the final token they will get assigned after the sorting.
4785  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4786  * with the reflection objects that represent them. Once all the tables are set up, the 
4787  * reflection objects will contains the correct table index. fixup_method() will fixup the
4788  * tokens for the method with ILGenerator @ilgen.
4789  */
4790 static void
4791 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4792 {
4793         guint32 code_idx = GPOINTER_TO_UINT (value);
4794         MonoReflectionILTokenInfo *iltoken;
4795         MonoReflectionFieldBuilder *field;
4796         MonoReflectionCtorBuilder *ctor;
4797         MonoReflectionMethodBuilder *method;
4798         MonoReflectionTypeBuilder *tb;
4799         MonoReflectionArrayMethod *am;
4800         guint32 i, idx = 0;
4801         unsigned char *target;
4802
4803         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4804                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4805                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4806                 switch (target [3]) {
4807                 case MONO_TABLE_FIELD:
4808                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4809                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4810                                 idx = field->table_idx;
4811                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4812                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4813                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4814                         } else {
4815                                 g_assert_not_reached ();
4816                         }
4817                         break;
4818                 case MONO_TABLE_METHOD:
4819                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4820                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4821                                 idx = method->table_idx;
4822                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4823                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4824                                 idx = ctor->table_idx;
4825                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4826                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4827                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4828                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4829                         } else {
4830                                 g_assert_not_reached ();
4831                         }
4832                         break;
4833                 case MONO_TABLE_TYPEDEF:
4834                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4835                                 g_assert_not_reached ();
4836                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4837                         idx = tb->table_idx;
4838                         break;
4839                 case MONO_TABLE_MEMBERREF:
4840                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4841                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4842                                 idx = am->table_idx;
4843                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4844                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4845                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4846                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4847                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4848                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4849                                 continue;
4850                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4851                                 continue;
4852                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4853                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4854                                 g_assert (is_field_on_inst (f));
4855                                 continue;
4856                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4857                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4858                                 continue;
4859                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4860                                 continue;
4861                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4862                                 continue;
4863                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4864                                 continue;
4865                         } else {
4866                                 g_assert_not_reached ();
4867                         }
4868                         break;
4869                 case MONO_TABLE_METHODSPEC:
4870                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4871                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4872                                 g_assert (mono_method_signature (m)->generic_param_count);
4873                                 continue;
4874                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4875                                 continue;
4876                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4877                                 continue;
4878                         } else {
4879                                 g_assert_not_reached ();
4880                         }
4881                         break;
4882                 default:
4883                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4884                 }
4885                 target [0] = idx & 0xff;
4886                 target [1] = (idx >> 8) & 0xff;
4887                 target [2] = (idx >> 16) & 0xff;
4888         }
4889 }
4890
4891 /*
4892  * fixup_cattrs:
4893  *
4894  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4895  * value is not known when the table is emitted.
4896  */
4897 static void
4898 fixup_cattrs (MonoDynamicImage *assembly)
4899 {
4900         MonoDynamicTable *table;
4901         guint32 *values;
4902         guint32 type, i, idx, token;
4903         MonoObject *ctor;
4904
4905         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4906
4907         for (i = 0; i < table->rows; ++i) {
4908                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4909
4910                 type = values [MONO_CUSTOM_ATTR_TYPE];
4911                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4912                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4913                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4914                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4915                         g_assert (ctor);
4916
4917                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4918                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4919                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4920                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4921                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4922                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4923                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4924                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4925                         }
4926                 }
4927         }
4928 }
4929
4930 static void
4931 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4932 {
4933         MonoDynamicTable *table;
4934         guint32 *values;
4935
4936         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4937         table->rows++;
4938         alloc_table (table, table->rows);
4939         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4940         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4941         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4942         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4943         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4944         table->next_idx++;
4945 }
4946
4947 static void
4948 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4949 {
4950         MonoDynamicTable *table;
4951         guint32 *values;
4952         char blob_size [6];
4953         guchar hash [20];
4954         char *b = blob_size;
4955         char *name, *sname;
4956         guint32 idx, offset;
4957
4958         if (rsrc->filename) {
4959                 name = mono_string_to_utf8 (rsrc->filename);
4960                 sname = g_path_get_basename (name);
4961         
4962                 table = &assembly->tables [MONO_TABLE_FILE];
4963                 table->rows++;
4964                 alloc_table (table, table->rows);
4965                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4966                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4967                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4968                 g_free (sname);
4969
4970                 mono_sha1_get_digest_from_file (name, hash);
4971                 mono_metadata_encode_value (20, b, &b);
4972                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4973                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4974                 g_free (name);
4975                 idx = table->next_idx++;
4976                 rsrc->offset = 0;
4977                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4978         } else {
4979                 char sizebuf [4];
4980                 char *data;
4981                 guint len;
4982                 if (rsrc->data) {
4983                         data = mono_array_addr (rsrc->data, char, 0);
4984                         len = mono_array_length (rsrc->data);
4985                 } else {
4986                         data = NULL;
4987                         len = 0;
4988                 }
4989                 offset = len;
4990                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4991                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4992                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4993                 mono_image_add_stream_data (&assembly->resources, data, len);
4994
4995                 if (!mb->is_main)
4996                         /* 
4997                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4998                          * the main module, but that needs to reference the FILE table
4999                          * which isn't emitted yet.
5000                          */
5001                         return;
5002                 else
5003                         idx = 0;
5004         }
5005
5006         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5007 }
5008
5009 static void
5010 set_version_from_string (MonoString *version, guint32 *values)
5011 {
5012         gchar *ver, *p, *str;
5013         guint32 i;
5014         
5015         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5016         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5017         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5018         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5019         if (!version)
5020                 return;
5021         ver = str = mono_string_to_utf8 (version);
5022         for (i = 0; i < 4; ++i) {
5023                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5024                 switch (*p) {
5025                 case '.':
5026                         p++;
5027                         break;
5028                 case '*':
5029                         /* handle Revision and Build */
5030                         p++;
5031                         break;
5032                 }
5033                 ver = p;
5034         }
5035         g_free (str);
5036 }
5037
5038 static guint32
5039 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5040         gsize len;
5041         guint32 token = 0;
5042         char blob_size [6];
5043         char *b = blob_size;
5044
5045         if (!pkey)
5046                 return token;
5047
5048         len = mono_array_length (pkey);
5049         mono_metadata_encode_value (len, b, &b);
5050         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5051         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5052
5053         assembly->public_key = (guint8 *)g_malloc (len);
5054         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5055         assembly->public_key_len = len;
5056
5057         /* Special case: check for ECMA key (16 bytes) */
5058         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5059                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5060                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5061         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5062                 /* minimum key size (in 2.0) is 384 bits */
5063                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5064         } else {
5065                 /* FIXME - verifier */
5066                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5067                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5068         }
5069         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5070
5071         return token;
5072 }
5073
5074 static void
5075 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5076 {
5077         MonoDynamicTable *table;
5078         MonoDynamicImage *assembly;
5079         MonoReflectionAssemblyBuilder *assemblyb;
5080         MonoDomain *domain;
5081         guint32 *values;
5082         int i;
5083         guint32 module_index;
5084
5085         mono_error_init (error);
5086
5087         assemblyb = moduleb->assemblyb;
5088         assembly = moduleb->dynamic_image;
5089         domain = mono_object_domain (assemblyb);
5090
5091         /* Emit ASSEMBLY table */
5092         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5093         alloc_table (table, 1);
5094         values = table->values + MONO_ASSEMBLY_SIZE;
5095         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5096         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5097         if (assemblyb->culture) {
5098                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5099         } else {
5100                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5101         }
5102         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5103         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5104         set_version_from_string (assemblyb->version, values);
5105
5106         /* Emit FILE + EXPORTED_TYPE table */
5107         module_index = 0;
5108         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5109                 int j;
5110                 MonoReflectionModuleBuilder *file_module = 
5111                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5112                 if (file_module != moduleb) {
5113                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5114                         module_index ++;
5115                         if (file_module->types) {
5116                                 for (j = 0; j < file_module->num_types; ++j) {
5117                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5118                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5119                                         return_if_nok (error);
5120                                 }
5121                         }
5122                 }
5123         }
5124         if (assemblyb->loaded_modules) {
5125                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5126                         MonoReflectionModule *file_module = 
5127                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5128                         mono_image_fill_file_table (domain, file_module, assembly);
5129                         module_index ++;
5130                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5131                 }
5132         }
5133         if (assemblyb->type_forwarders)
5134                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5135
5136         /* Emit MANIFESTRESOURCE table */
5137         module_index = 0;
5138         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5139                 int j;
5140                 MonoReflectionModuleBuilder *file_module = 
5141                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5142                 /* The table for the main module is emitted later */
5143                 if (file_module != moduleb) {
5144                         module_index ++;
5145                         if (file_module->resources) {
5146                                 int len = mono_array_length (file_module->resources);
5147                                 for (j = 0; j < len; ++j) {
5148                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5149                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5150                                 }
5151                         }
5152                 }
5153         }               
5154 }
5155
5156 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5157
5158 /*
5159  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5160  * for the modulebuilder @moduleb.
5161  * At the end of the process, method and field tokens are fixed up and the 
5162  * on-disk compressed metadata representation is created.
5163  * Return TRUE on success, or FALSE on failure and sets @error
5164  */
5165 gboolean
5166 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5167 {
5168         MonoDynamicTable *table;
5169         MonoDynamicImage *assembly;
5170         MonoReflectionAssemblyBuilder *assemblyb;
5171         MonoDomain *domain;
5172         MonoPtrArray types;
5173         guint32 *values;
5174         int i, j;
5175
5176         mono_error_init (error);
5177
5178         assemblyb = moduleb->assemblyb;
5179         assembly = moduleb->dynamic_image;
5180         domain = mono_object_domain (assemblyb);
5181
5182         if (assembly->text_rva)
5183                 return TRUE;
5184
5185         assembly->text_rva = START_TEXT_RVA;
5186
5187         if (moduleb->is_main) {
5188                 mono_image_emit_manifest (moduleb, error);
5189                 return_val_if_nok (error, FALSE);
5190         }
5191
5192         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5193         table->rows = 1; /* .<Module> */
5194         table->next_idx++;
5195         alloc_table (table, table->rows);
5196         /*
5197          * Set the first entry.
5198          */
5199         values = table->values + table->columns;
5200         values [MONO_TYPEDEF_FLAGS] = 0;
5201         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5202         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5203         values [MONO_TYPEDEF_EXTENDS] = 0;
5204         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5205         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5206
5207         /* 
5208          * handle global methods 
5209          * FIXME: test what to do when global methods are defined in multiple modules.
5210          */
5211         if (moduleb->global_methods) {
5212                 table = &assembly->tables [MONO_TABLE_METHOD];
5213                 table->rows += mono_array_length (moduleb->global_methods);
5214                 alloc_table (table, table->rows);
5215                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5216                         if (!mono_image_get_method_info (
5217                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5218                                 goto leave;
5219                 }
5220         }
5221         if (moduleb->global_fields) {
5222                 table = &assembly->tables [MONO_TABLE_FIELD];
5223                 table->rows += mono_array_length (moduleb->global_fields);
5224                 alloc_table (table, table->rows);
5225                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5226                         mono_image_get_field_info (
5227                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5228                                 error);
5229                         if (!is_ok (error))
5230                                 goto leave;
5231                 }
5232         }
5233
5234         table = &assembly->tables [MONO_TABLE_MODULE];
5235         alloc_table (table, 1);
5236         mono_image_fill_module_table (domain, moduleb, assembly);
5237
5238         /* Collect all types into a list sorted by their table_idx */
5239         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5240
5241         if (moduleb->types)
5242                 for (i = 0; i < moduleb->num_types; ++i) {
5243                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5244                         collect_types (&types, type);
5245                 }
5246
5247         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5248         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5249         table->rows += mono_ptr_array_size (types);
5250         alloc_table (table, table->rows);
5251
5252         /*
5253          * Emit type names + namespaces at one place inside the string heap,
5254          * so load_class_names () needs to touch fewer pages.
5255          */
5256         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5257                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5258                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5259         }
5260         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5261                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5262                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5263         }
5264
5265         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5266                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5267                 if (!mono_image_get_type_info (domain, type, assembly, error))
5268                         goto leave_types;
5269         }
5270
5271         /* 
5272          * table->rows is already set above and in mono_image_fill_module_table.
5273          */
5274         /* add all the custom attributes at the end, once all the indexes are stable */
5275         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5276                 goto leave_types;
5277
5278         /* CAS assembly permissions */
5279         if (assemblyb->permissions_minimum)
5280                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5281         if (assemblyb->permissions_optional)
5282                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5283         if (assemblyb->permissions_refused)
5284                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5285
5286         if (!module_add_cattrs (assembly, moduleb, error))
5287                 goto leave_types;
5288
5289         /* fixup tokens */
5290         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5291
5292         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5293          * the final tokens and don't need another fixup pass. */
5294
5295         if (moduleb->global_methods) {
5296                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5297                         MonoReflectionMethodBuilder *mb = mono_array_get (
5298                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5299                         if (!mono_image_add_methodimpl (assembly, mb, error))
5300                                 goto leave_types;
5301                 }
5302         }
5303
5304         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5305                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5306                 if (type->methods) {
5307                         for (j = 0; j < type->num_methods; ++j) {
5308                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5309                                         type->methods, MonoReflectionMethodBuilder*, j);
5310
5311                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5312                                         goto leave_types;
5313                         }
5314                 }
5315         }
5316
5317         fixup_cattrs (assembly);
5318
5319 leave_types:
5320         mono_ptr_array_destroy (types);
5321 leave:
5322
5323         return mono_error_ok (error);
5324 }
5325
5326 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5327
5328 gboolean
5329 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5330 {
5331         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5332 }
5333
5334 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5335
5336
5337 typedef struct {
5338         guint32 import_lookup_table;
5339         guint32 timestamp;
5340         guint32 forwarder;
5341         guint32 name_rva;
5342         guint32 import_address_table_rva;
5343 } MonoIDT;
5344
5345 typedef struct {
5346         guint32 name_rva;
5347         guint32 flags;
5348 } MonoILT;
5349
5350 #ifndef DISABLE_REFLECTION_EMIT
5351
5352 /*
5353  * mono_image_insert_string:
5354  * @module: module builder object
5355  * @str: a string
5356  *
5357  * Insert @str into the user string stream of @module.
5358  */
5359 guint32
5360 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5361 {
5362         MonoDynamicImage *assembly;
5363         guint32 idx;
5364         char buf [16];
5365         char *b = buf;
5366         
5367         if (!module->dynamic_image)
5368                 mono_image_module_basic_init (module);
5369
5370         assembly = module->dynamic_image;
5371         
5372         if (assembly->save) {
5373                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5374                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5375 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5376         {
5377                 char *swapped = g_malloc (2 * mono_string_length (str));
5378                 const char *p = (const char*)mono_string_chars (str);
5379
5380                 swap_with_size (swapped, p, 2, mono_string_length (str));
5381                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5382                 g_free (swapped);
5383         }
5384 #else
5385                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5386 #endif
5387                 mono_image_add_stream_data (&assembly->us, "", 1);
5388         } else {
5389                 idx = assembly->us.index ++;
5390         }
5391
5392         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5393
5394         return MONO_TOKEN_STRING | idx;
5395 }
5396
5397 guint32
5398 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5399 {
5400         MonoClass *klass;
5401         guint32 token = 0;
5402         MonoMethodSignature *sig;
5403
5404         mono_error_init (error);
5405
5406         klass = obj->vtable->klass;
5407         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5408                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5409                 MonoMethodSignature *old;
5410                 guint32 sig_token, parent;
5411                 int nargs, i;
5412
5413                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5414
5415                 nargs = mono_array_length (opt_param_types);
5416                 old = mono_method_signature (method);
5417                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5418
5419                 sig->hasthis = old->hasthis;
5420                 sig->explicit_this = old->explicit_this;
5421                 sig->call_convention = old->call_convention;
5422                 sig->generic_param_count = old->generic_param_count;
5423                 sig->param_count = old->param_count + nargs;
5424                 sig->sentinelpos = old->param_count;
5425                 sig->ret = old->ret;
5426
5427                 for (i = 0; i < old->param_count; i++)
5428                         sig->params [i] = old->params [i];
5429
5430                 for (i = 0; i < nargs; i++) {
5431                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5432                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5433                         if (!is_ok (error)) goto fail;
5434                 }
5435
5436                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5437                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5438                 parent >>= MONO_TYPEDEFORREF_BITS;
5439
5440                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5441                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5442
5443                 sig_token = method_encode_signature (assembly, sig);
5444                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5445         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5446                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5447                 ReflectionMethodBuilder rmb;
5448                 guint32 parent, sig_token;
5449                 int nopt_args, nparams, ngparams, i;
5450
5451                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5452                         goto fail;
5453                 
5454                 rmb.opt_types = opt_param_types;
5455                 nopt_args = mono_array_length (opt_param_types);
5456
5457                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5458                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5459                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5460
5461                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5462                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5463                 sig->call_convention = rmb.call_conv;
5464                 sig->generic_param_count = ngparams;
5465                 sig->param_count = nparams + nopt_args;
5466                 sig->sentinelpos = nparams;
5467                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5468                 if (!is_ok (error)) goto fail;
5469
5470                 for (i = 0; i < nparams; i++) {
5471                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5472                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5473                         if (!is_ok (error)) goto fail;
5474                 }
5475
5476                 for (i = 0; i < nopt_args; i++) {
5477                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5478                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5479                         if (!is_ok (error)) goto fail;
5480                 }
5481
5482                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5483                 if (!is_ok (error))
5484                         goto fail;
5485
5486                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5487                 if (!mono_error_ok (error))
5488                         goto fail;
5489                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5490
5491                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5492                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5493
5494                 char *name = mono_string_to_utf8 (rmb.name);
5495                 token = mono_image_get_varargs_method_token (
5496                         assembly, parent, name, sig_token);
5497                 g_free (name);
5498         } else {
5499                 g_error ("requested method token for %s\n", klass->name);
5500         }
5501
5502         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5503         register_dyn_token (assembly, token, obj);
5504         return token;
5505 fail:
5506         g_assert (!mono_error_ok (error));
5507         return 0;
5508 }
5509
5510 /*
5511  * mono_image_create_token:
5512  * @assembly: a dynamic assembly
5513  * @obj:
5514  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5515  *
5516  * Get a token to insert in the IL code stream for the given MemberInfo.
5517  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5518  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5519  * entry.
5520  */
5521 guint32
5522 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5523                          gboolean create_open_instance, gboolean register_token,
5524                          MonoError *error)
5525 {
5526         MonoClass *klass;
5527         guint32 token = 0;
5528
5529         mono_error_init (error);
5530
5531         klass = obj->vtable->klass;
5532
5533         /* Check for user defined reflection objects */
5534         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5535         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5536                 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5537                 return 0;
5538         }
5539
5540         if (strcmp (klass->name, "MethodBuilder") == 0) {
5541                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5542                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5543
5544                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5545                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5546                 else {
5547                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5548                         if (!mono_error_ok (error))
5549                                 return 0;
5550                 }
5551                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5552         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5553                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5554                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5555
5556                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5557                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5558                 else {
5559                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5560                         if (!mono_error_ok (error))
5561                                 return 0;
5562                 }
5563                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5564         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5565                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5566                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5567                 if (tb->generic_params) {
5568                         token = mono_image_get_generic_field_token (assembly, fb, error);
5569                         return_val_if_nok (error, 0);
5570                 } else {
5571                         if (tb->module->dynamic_image == assembly) {
5572                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5573                         } else {
5574                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5575                         }
5576                 }
5577         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5578                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5579                 if (create_open_instance && tb->generic_params) {
5580                         MonoType *type;
5581                         init_type_builder_generics (obj);
5582                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5583                         return_val_if_nok (error, 0);
5584                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5585                         token = mono_metadata_token_from_dor (token);
5586                 } else if (tb->module->dynamic_image == assembly) {
5587                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5588                 } else {
5589                         MonoType *type;
5590                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5591                         return_val_if_nok (error, 0);
5592                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5593                 }
5594         } else if (strcmp (klass->name, "MonoType") == 0) {
5595                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5596                 return_val_if_nok (error, 0);
5597                 MonoClass *mc = mono_class_from_mono_type (type);
5598                 token = mono_metadata_token_from_dor (
5599                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5600         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5601                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5602                 return_val_if_nok (error, 0);
5603                 token = mono_metadata_token_from_dor (
5604                         mono_image_typedef_or_ref (assembly, type));
5605         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5606                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5607                 return_val_if_nok (error, 0);
5608                 token = mono_metadata_token_from_dor (
5609                         mono_image_typedef_or_ref (assembly, type));
5610         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5611                    strcmp (klass->name, "MonoMethod") == 0 ||
5612                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5613                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5614                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5615                 if (m->method->is_inflated) {
5616                         if (create_open_instance)
5617                                 token = mono_image_get_methodspec_token (assembly, m->method);
5618                         else
5619                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5620                 } else if ((m->method->klass->image == &assembly->image) &&
5621                          !m->method->klass->generic_class) {
5622                         static guint32 method_table_idx = 0xffffff;
5623                         if (m->method->klass->wastypebuilder) {
5624                                 /* we use the same token as the one that was assigned
5625                                  * to the Methodbuilder.
5626                                  * FIXME: do the equivalent for Fields.
5627                                  */
5628                                 token = m->method->token;
5629                         } else {
5630                                 /*
5631                                  * Each token should have a unique index, but the indexes are
5632                                  * assigned by managed code, so we don't know about them. An
5633                                  * easy solution is to count backwards...
5634                                  */
5635                                 method_table_idx --;
5636                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5637                         }
5638                 } else {
5639                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5640                 }
5641                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5642         } else if (strcmp (klass->name, "MonoField") == 0) {
5643                 MonoReflectionField *f = (MonoReflectionField *)obj;
5644                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5645                         static guint32 field_table_idx = 0xffffff;
5646                         field_table_idx --;
5647                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5648                 } else {
5649                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5650                 }
5651                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5652         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5653                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5654                 token = mono_image_get_array_token (assembly, m, error);
5655                 return_val_if_nok (error, 0);
5656         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5657                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5658                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5659                 return_val_if_nok (error, 0);
5660         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5661                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5662                 return_val_if_nok (error, 0);
5663                 token = mono_metadata_token_from_dor (
5664                         mono_image_typedef_or_ref (assembly, type));
5665         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5666                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5667                 token = mono_image_get_field_on_inst_token (assembly, f, error);
5668                 return_val_if_nok (error, 0);
5669         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5670                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5671                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5672                 if (!mono_error_ok (error))
5673                         return 0;
5674         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5675                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5676                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5677                 if (!mono_error_ok (error))
5678                         return 0;
5679         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5680                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5681                 return_val_if_nok (error, 0);
5682                 token = mono_metadata_token_from_dor (
5683                                 mono_image_typedef_or_ref (assembly, type));
5684         } else {
5685                 g_error ("requested token for %s\n", klass->name);
5686         }
5687
5688         if (register_token)
5689                 mono_image_register_token (assembly, token, obj);
5690
5691         return token;
5692 }
5693
5694 /*
5695  * mono_image_register_token:
5696  *
5697  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5698  * the Module.ResolveXXXToken () methods to work.
5699  */
5700 void
5701 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5702 {
5703         MonoObject *prev;
5704
5705         dynamic_image_lock (assembly);
5706         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5707         if (prev) {
5708                 /* There could be multiple MethodInfo objects with the same token */
5709                 //g_assert (prev == obj);
5710         } else {
5711                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5712         }
5713         dynamic_image_unlock (assembly);
5714 }
5715
5716 static MonoDynamicImage*
5717 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5718 {
5719         static const guchar entrycode [16] = {0xff, 0x25, 0};
5720         MonoDynamicImage *image;
5721         int i;
5722
5723         const char *version;
5724
5725         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5726                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5727         else
5728                 version = mono_get_runtime_info ()->runtime_version;
5729
5730 #if HAVE_BOEHM_GC
5731         /* The MonoGHashTable's need GC tracking */
5732         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5733 #else
5734         image = g_new0 (MonoDynamicImage, 1);
5735 #endif
5736
5737         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5738         
5739         /*g_print ("created image %p\n", image);*/
5740         /* keep in sync with image.c */
5741         image->image.name = assembly_name;
5742         image->image.assembly_name = image->image.name; /* they may be different */
5743         image->image.module_name = module_name;
5744         image->image.version = g_strdup (version);
5745         image->image.md_version_major = 1;
5746         image->image.md_version_minor = 1;
5747         image->image.dynamic = TRUE;
5748
5749         image->image.references = g_new0 (MonoAssembly*, 1);
5750         image->image.references [0] = NULL;
5751
5752         mono_image_init (&image->image);
5753
5754         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");
5755         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5756         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5757         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5758         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5759         image->handleref = g_hash_table_new (NULL, NULL);
5760         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");
5761         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5762         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");
5763         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");
5764         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5765         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5766         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5767         image->gen_params = g_ptr_array_new ();
5768         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5769
5770         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5771         string_heap_init (&image->sheap);
5772         mono_image_add_stream_data (&image->us, "", 1);
5773         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5774         /* import tables... */
5775         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5776         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5777         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5778         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5779         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5780         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5781         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5782         stream_data_align (&image->code);
5783
5784         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5785
5786         for (i=0; i < MONO_TABLE_NUM; ++i) {
5787                 image->tables [i].next_idx = 1;
5788                 image->tables [i].columns = table_sizes [i];
5789         }
5790
5791         image->image.assembly = (MonoAssembly*)assembly;
5792         image->run = assembly->run;
5793         image->save = assembly->save;
5794         image->pe_kind = 0x1; /* ILOnly */
5795         image->machine = 0x14c; /* I386 */
5796         
5797         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5798
5799         dynamic_images_lock ();
5800
5801         if (!dynamic_images)
5802                 dynamic_images = g_ptr_array_new ();
5803
5804         g_ptr_array_add (dynamic_images, image);
5805
5806         dynamic_images_unlock ();
5807
5808         return image;
5809 }
5810 #endif
5811
5812 static void
5813 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5814 {
5815         g_free (key);
5816 }
5817
5818 static void
5819 release_hashtable (MonoGHashTable **hash)
5820 {
5821         if (*hash) {
5822                 mono_g_hash_table_destroy (*hash);
5823                 *hash = NULL;
5824         }
5825 }
5826
5827 void
5828 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5829 {
5830         release_hashtable (&image->token_fixups);
5831         release_hashtable (&image->handleref_managed);
5832         release_hashtable (&image->tokens);
5833         release_hashtable (&image->remapped_tokens);
5834         release_hashtable (&image->generic_def_objects);
5835         release_hashtable (&image->methodspec);
5836 }
5837
5838 // Free dynamic image pass one: Free resources but not image itself
5839 void
5840 mono_dynamic_image_free (MonoDynamicImage *image)
5841 {
5842         MonoDynamicImage *di = image;
5843         GList *list;
5844         int i;
5845
5846         if (di->methodspec)
5847                 mono_g_hash_table_destroy (di->methodspec);
5848         if (di->typespec)
5849                 g_hash_table_destroy (di->typespec);
5850         if (di->typeref)
5851                 g_hash_table_destroy (di->typeref);
5852         if (di->handleref)
5853                 g_hash_table_destroy (di->handleref);
5854         if (di->handleref_managed)
5855                 mono_g_hash_table_destroy (di->handleref_managed);
5856         if (di->tokens)
5857                 mono_g_hash_table_destroy (di->tokens);
5858         if (di->remapped_tokens)
5859                 mono_g_hash_table_destroy (di->remapped_tokens);
5860         if (di->generic_def_objects)
5861                 mono_g_hash_table_destroy (di->generic_def_objects);
5862         if (di->blob_cache) {
5863                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5864                 g_hash_table_destroy (di->blob_cache);
5865         }
5866         if (di->standalonesig_cache)
5867                 g_hash_table_destroy (di->standalonesig_cache);
5868         for (list = di->array_methods; list; list = list->next) {
5869                 ArrayMethod *am = (ArrayMethod *)list->data;
5870                 g_free (am->sig);
5871                 g_free (am->name);
5872                 g_free (am);
5873         }
5874         g_list_free (di->array_methods);
5875         if (di->gen_params) {
5876                 for (i = 0; i < di->gen_params->len; i++) {
5877                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5878                         mono_gc_deregister_root ((char*) &entry->gparam);
5879                         g_free (entry);
5880                 }
5881                 g_ptr_array_free (di->gen_params, TRUE);
5882         }
5883         if (di->token_fixups)
5884                 mono_g_hash_table_destroy (di->token_fixups);
5885         if (di->method_to_table_idx)
5886                 g_hash_table_destroy (di->method_to_table_idx);
5887         if (di->field_to_table_idx)
5888                 g_hash_table_destroy (di->field_to_table_idx);
5889         if (di->method_aux_hash)
5890                 g_hash_table_destroy (di->method_aux_hash);
5891         if (di->vararg_aux_hash)
5892                 g_hash_table_destroy (di->vararg_aux_hash);
5893         g_free (di->strong_name);
5894         g_free (di->win32_res);
5895         if (di->public_key)
5896                 g_free (di->public_key);
5897
5898         /*g_print ("string heap destroy for image %p\n", di);*/
5899         mono_dynamic_stream_reset (&di->sheap);
5900         mono_dynamic_stream_reset (&di->code);
5901         mono_dynamic_stream_reset (&di->resources);
5902         mono_dynamic_stream_reset (&di->us);
5903         mono_dynamic_stream_reset (&di->blob);
5904         mono_dynamic_stream_reset (&di->tstream);
5905         mono_dynamic_stream_reset (&di->guid);
5906         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5907                 g_free (di->tables [i].values);
5908         }
5909
5910         dynamic_images_lock ();
5911
5912         if (dynamic_images)
5913                 g_ptr_array_remove (dynamic_images, di);
5914
5915         dynamic_images_unlock ();
5916 }
5917
5918 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5919 void
5920 mono_dynamic_image_free_image (MonoDynamicImage *image)
5921 {
5922         /* See create_dynamic_mono_image () */
5923 #if HAVE_BOEHM_GC
5924         /* Allocated using GC_MALLOC */
5925 #else
5926         g_free (image);
5927 #endif
5928 }
5929
5930 #ifndef DISABLE_REFLECTION_EMIT
5931
5932 /*
5933  * mono_image_basic_init:
5934  * @assembly: an assembly builder object
5935  *
5936  * Create the MonoImage that represents the assembly builder and setup some
5937  * of the helper hash table and the basic metadata streams.
5938  */
5939 void
5940 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5941 {
5942         MonoDynamicAssembly *assembly;
5943         MonoDynamicImage *image;
5944         MonoDomain *domain = mono_object_domain (assemblyb);
5945         
5946         if (assemblyb->dynamic_assembly)
5947                 return;
5948
5949 #if HAVE_BOEHM_GC
5950         /* assembly->assembly.image might be GC allocated */
5951         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5952 #else
5953         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5954 #endif
5955
5956         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5957         
5958         assembly->assembly.ref_count = 1;
5959         assembly->assembly.dynamic = TRUE;
5960         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5961         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5962         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5963         if (assemblyb->culture)
5964                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5965         else
5966                 assembly->assembly.aname.culture = g_strdup ("");
5967
5968         if (assemblyb->version) {
5969                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5970                         char **version = g_strsplit (vstr, ".", 4);
5971                         char **parts = version;
5972                         assembly->assembly.aname.major = atoi (*parts++);
5973                         assembly->assembly.aname.minor = atoi (*parts++);
5974                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5975                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5976
5977                         g_strfreev (version);
5978                         g_free (vstr);
5979         } else {
5980                         assembly->assembly.aname.major = 0;
5981                         assembly->assembly.aname.minor = 0;
5982                         assembly->assembly.aname.build = 0;
5983                         assembly->assembly.aname.revision = 0;
5984         }
5985
5986         assembly->run = assemblyb->access != 2;
5987         assembly->save = assemblyb->access != 1;
5988         assembly->domain = domain;
5989
5990         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5991         image->initial_image = TRUE;
5992         assembly->assembly.aname.name = image->image.name;
5993         assembly->assembly.image = &image->image;
5994         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5995                 /* -1 to correct for the trailing NULL byte */
5996                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5997                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5998                 }
5999                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
6000         }
6001
6002         mono_domain_assemblies_lock (domain);
6003         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6004         mono_domain_assemblies_unlock (domain);
6005
6006         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6007         
6008         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6009         
6010         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6011 }
6012
6013 #endif /* !DISABLE_REFLECTION_EMIT */
6014
6015 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6016
6017 static int
6018 calc_section_size (MonoDynamicImage *assembly)
6019 {
6020         int nsections = 0;
6021
6022         /* alignment constraints */
6023         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6024         g_assert ((assembly->code.index % 4) == 0);
6025         assembly->meta_size += 3;
6026         assembly->meta_size &= ~3;
6027         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6028         g_assert ((assembly->resources.index % 4) == 0);
6029
6030         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6031         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6032         nsections++;
6033
6034         if (assembly->win32_res) {
6035                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6036
6037                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6038                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6039                 nsections++;
6040         }
6041
6042         assembly->sections [MONO_SECTION_RELOC].size = 12;
6043         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6044         nsections++;
6045
6046         return nsections;
6047 }
6048
6049 typedef struct {
6050         guint32 id;
6051         guint32 offset;
6052         GSList *children;
6053         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6054 } ResTreeNode;
6055
6056 static int
6057 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6058 {
6059         ResTreeNode *t1 = (ResTreeNode*)a;
6060         ResTreeNode *t2 = (ResTreeNode*)b;
6061
6062         return t1->id - t2->id;
6063 }
6064
6065 /*
6066  * resource_tree_create:
6067  *
6068  *  Organize the resources into a resource tree.
6069  */
6070 static ResTreeNode *
6071 resource_tree_create (MonoArray *win32_resources)
6072 {
6073         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6074         GSList *l;
6075         int i;
6076
6077         tree = g_new0 (ResTreeNode, 1);
6078         
6079         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6080                 MonoReflectionWin32Resource *win32_res =
6081                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6082
6083                 /* Create node */
6084
6085                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6086                 lang_node = g_new0 (ResTreeNode, 1);
6087                 lang_node->id = win32_res->lang_id;
6088                 lang_node->win32_res = win32_res;
6089
6090                 /* Create type node if neccesary */
6091                 type_node = NULL;
6092                 for (l = tree->children; l; l = l->next)
6093                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6094                                 type_node = (ResTreeNode*)l->data;
6095                                 break;
6096                         }
6097
6098                 if (!type_node) {
6099                         type_node = g_new0 (ResTreeNode, 1);
6100                         type_node->id = win32_res->res_type;
6101
6102                         /* 
6103                          * The resource types have to be sorted otherwise
6104                          * Windows Explorer can't display the version information.
6105                          */
6106                         tree->children = g_slist_insert_sorted (tree->children, 
6107                                 type_node, resource_tree_compare_by_id);
6108                 }
6109
6110                 /* Create res node if neccesary */
6111                 res_node = NULL;
6112                 for (l = type_node->children; l; l = l->next)
6113                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6114                                 res_node = (ResTreeNode*)l->data;
6115                                 break;
6116                         }
6117
6118                 if (!res_node) {
6119                         res_node = g_new0 (ResTreeNode, 1);
6120                         res_node->id = win32_res->res_id;
6121                         type_node->children = g_slist_append (type_node->children, res_node);
6122                 }
6123
6124                 res_node->children = g_slist_append (res_node->children, lang_node);
6125         }
6126
6127         return tree;
6128 }
6129
6130 /*
6131  * resource_tree_encode:
6132  * 
6133  *   Encode the resource tree into the format used in the PE file.
6134  */
6135 static void
6136 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6137 {
6138         char *entries;
6139         MonoPEResourceDir dir;
6140         MonoPEResourceDirEntry dir_entry;
6141         MonoPEResourceDataEntry data_entry;
6142         GSList *l;
6143         guint32 res_id_entries;
6144
6145         /*
6146          * For the format of the resource directory, see the article
6147          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6148          * Matt Pietrek
6149          */
6150
6151         memset (&dir, 0, sizeof (dir));
6152         memset (&dir_entry, 0, sizeof (dir_entry));
6153         memset (&data_entry, 0, sizeof (data_entry));
6154
6155         g_assert (sizeof (dir) == 16);
6156         g_assert (sizeof (dir_entry) == 8);
6157         g_assert (sizeof (data_entry) == 16);
6158
6159         node->offset = p - begin;
6160
6161         /* IMAGE_RESOURCE_DIRECTORY */
6162         res_id_entries = g_slist_length (node->children);
6163         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6164
6165         memcpy (p, &dir, sizeof (dir));
6166         p += sizeof (dir);
6167
6168         /* Reserve space for entries */
6169         entries = p;
6170         p += sizeof (dir_entry) * res_id_entries;
6171
6172         /* Write children */
6173         for (l = node->children; l; l = l->next) {
6174                 ResTreeNode *child = (ResTreeNode*)l->data;
6175
6176                 if (child->win32_res) {
6177                         guint32 size;
6178
6179                         child->offset = p - begin;
6180
6181                         /* IMAGE_RESOURCE_DATA_ENTRY */
6182                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6183                         size = mono_array_length (child->win32_res->res_data);
6184                         data_entry.rde_size = GUINT32_TO_LE (size);
6185
6186                         memcpy (p, &data_entry, sizeof (data_entry));
6187                         p += sizeof (data_entry);
6188
6189                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6190                         p += size;
6191                 } else {
6192                         resource_tree_encode (child, begin, p, &p);
6193                 }
6194         }
6195
6196         /* IMAGE_RESOURCE_ENTRY */
6197         for (l = node->children; l; l = l->next) {
6198                 ResTreeNode *child = (ResTreeNode*)l->data;
6199
6200                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6201                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6202
6203                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6204                 entries += sizeof (dir_entry);
6205         }
6206
6207         *endbuf = p;
6208 }
6209
6210 static void
6211 resource_tree_free (ResTreeNode * node)
6212 {
6213         GSList * list;
6214         for (list = node->children; list; list = list->next)
6215                 resource_tree_free ((ResTreeNode*)list->data);
6216         g_slist_free(node->children);
6217         g_free (node);
6218 }
6219
6220 static void
6221 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6222 {
6223         char *buf;
6224         char *p;
6225         guint32 size, i;
6226         MonoReflectionWin32Resource *win32_res;
6227         ResTreeNode *tree;
6228
6229         if (!assemblyb->win32_resources)
6230                 return;
6231
6232         /*
6233          * Resources are stored in a three level tree inside the PE file.
6234          * - level one contains a node for each type of resource
6235          * - level two contains a node for each resource
6236          * - level three contains a node for each instance of a resource for a
6237          *   specific language.
6238          */
6239
6240         tree = resource_tree_create (assemblyb->win32_resources);
6241
6242         /* Estimate the size of the encoded tree */
6243         size = 0;
6244         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6245                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6246                 size += mono_array_length (win32_res->res_data);
6247         }
6248         /* Directory structure */
6249         size += mono_array_length (assemblyb->win32_resources) * 256;
6250         p = buf = (char *)g_malloc (size);
6251
6252         resource_tree_encode (tree, p, p, &p);
6253
6254         g_assert (p - buf <= size);
6255
6256         assembly->win32_res = (char *)g_malloc (p - buf);
6257         assembly->win32_res_size = p - buf;
6258         memcpy (assembly->win32_res, buf, p - buf);
6259
6260         g_free (buf);
6261         resource_tree_free (tree);
6262 }
6263
6264 static void
6265 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6266 {
6267         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6268         int i;
6269
6270         p += sizeof (MonoPEResourceDir);
6271         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6272                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6273                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6274                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6275                         fixup_resource_directory (res_section, child, rva);
6276                 } else {
6277                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6278                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6279                 }
6280
6281                 p += sizeof (MonoPEResourceDirEntry);
6282         }
6283 }
6284
6285 static void
6286 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6287 {
6288         guint32 dummy;
6289         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6290                 g_error ("WriteFile returned %d\n", GetLastError ());
6291 }
6292
6293 /*
6294  * mono_image_create_pefile:
6295  * @mb: a module builder object
6296  * 
6297  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6298  * assembly->pefile where it can be easily retrieved later in chunks.
6299  */
6300 gboolean
6301 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6302 {
6303         MonoMSDOSHeader *msdos;
6304         MonoDotNetHeader *header;
6305         MonoSectionTable *section;
6306         MonoCLIHeader *cli_header;
6307         guint32 size, image_size, virtual_base, text_offset;
6308         guint32 header_start, section_start, file_offset, virtual_offset;
6309         MonoDynamicImage *assembly;
6310         MonoReflectionAssemblyBuilder *assemblyb;
6311         MonoDynamicStream pefile_stream = {0};
6312         MonoDynamicStream *pefile = &pefile_stream;
6313         int i, nsections;
6314         guint32 *rva, value;
6315         guchar *p;
6316         static const unsigned char msheader[] = {
6317                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6318                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6319                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6320                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6321                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6322                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6323                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6324                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6325         };
6326
6327         mono_error_init (error);
6328
6329         assemblyb = mb->assemblyb;
6330
6331         mono_image_basic_init (assemblyb);
6332         assembly = mb->dynamic_image;
6333
6334         assembly->pe_kind = assemblyb->pe_kind;
6335         assembly->machine = assemblyb->machine;
6336         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6337         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6338         
6339         if (!mono_image_build_metadata (mb, error))
6340                 return FALSE;
6341         
6342
6343         if (mb->is_main && assemblyb->resources) {
6344                 int len = mono_array_length (assemblyb->resources);
6345                 for (i = 0; i < len; ++i)
6346                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6347         }
6348
6349         if (mb->resources) {
6350                 int len = mono_array_length (mb->resources);
6351                 for (i = 0; i < len; ++i)
6352                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6353         }
6354
6355         if (!build_compressed_metadata (assembly, error))
6356                 return FALSE;
6357
6358         if (mb->is_main)
6359                 assembly_add_win32_resources (assembly, assemblyb);
6360
6361         nsections = calc_section_size (assembly);
6362         
6363         /* The DOS header and stub */
6364         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6365         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6366
6367         /* the dotnet header */
6368         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6369
6370         /* the section tables */
6371         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6372
6373         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6374         virtual_offset = VIRT_ALIGN;
6375         image_size = 0;
6376
6377         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6378                 if (!assembly->sections [i].size)
6379                         continue;
6380                 /* align offsets */
6381                 file_offset += FILE_ALIGN - 1;
6382                 file_offset &= ~(FILE_ALIGN - 1);
6383                 virtual_offset += VIRT_ALIGN - 1;
6384                 virtual_offset &= ~(VIRT_ALIGN - 1);
6385
6386                 assembly->sections [i].offset = file_offset;
6387                 assembly->sections [i].rva = virtual_offset;
6388
6389                 file_offset += assembly->sections [i].size;
6390                 virtual_offset += assembly->sections [i].size;
6391                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6392         }
6393
6394         file_offset += FILE_ALIGN - 1;
6395         file_offset &= ~(FILE_ALIGN - 1);
6396
6397         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6398
6399         /* back-patch info */
6400         msdos = (MonoMSDOSHeader*)pefile->data;
6401         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6402
6403         header = (MonoDotNetHeader*)(pefile->data + header_start);
6404         header->pesig [0] = 'P';
6405         header->pesig [1] = 'E';
6406         
6407         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6408         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6409         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6410         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6411         if (assemblyb->pekind == 1) {
6412                 /* it's a dll */
6413                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6414         } else {
6415                 /* it's an exe */
6416                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6417         }
6418
6419         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6420
6421         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6422         header->pe.pe_major = 6;
6423         header->pe.pe_minor = 0;
6424         size = assembly->sections [MONO_SECTION_TEXT].size;
6425         size += FILE_ALIGN - 1;
6426         size &= ~(FILE_ALIGN - 1);
6427         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6428         size = assembly->sections [MONO_SECTION_RSRC].size;
6429         size += FILE_ALIGN - 1;
6430         size &= ~(FILE_ALIGN - 1);
6431         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6432         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6433         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6434         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6435         /* pe_rva_entry_point always at the beginning of the text section */
6436         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6437
6438         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6439         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6440         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6441         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6442         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6443         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6444         size = section_start;
6445         size += FILE_ALIGN - 1;
6446         size &= ~(FILE_ALIGN - 1);
6447         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6448         size = image_size;
6449         size += VIRT_ALIGN - 1;
6450         size &= ~(VIRT_ALIGN - 1);
6451         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6452
6453         /*
6454         // Translate the PEFileKind value to the value expected by the Windows loader
6455         */
6456         {
6457                 short kind;
6458
6459                 /*
6460                 // PEFileKinds.Dll == 1
6461                 // PEFileKinds.ConsoleApplication == 2
6462                 // PEFileKinds.WindowApplication == 3
6463                 //
6464                 // need to get:
6465                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6466                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6467                 */
6468                 if (assemblyb->pekind == 3)
6469                         kind = 2;
6470                 else
6471                         kind = 3;
6472                 
6473                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6474         }    
6475         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6476         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6477         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6478         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6479         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6480         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6481
6482         /* fill data directory entries */
6483
6484         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6485         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6486
6487         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6488         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6489
6490         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6491         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6492         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6493         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6494         /* patch entrypoint name */
6495         if (assemblyb->pekind == 1)
6496                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6497         else
6498                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6499         /* patch imported function RVA name */
6500         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6501         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6502
6503         /* the import table */
6504         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6505         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6506         /* patch imported dll RVA name and other entries in the dir */
6507         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6508         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6509         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6510         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6511         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6512         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6513
6514         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6515         value = (assembly->text_rva + assembly->imp_names_offset);
6516         *p++ = (value) & 0xff;
6517         *p++ = (value >> 8) & (0xff);
6518         *p++ = (value >> 16) & (0xff);
6519         *p++ = (value >> 24) & (0xff);
6520
6521         /* the CLI header info */
6522         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6523         cli_header->ch_size = GUINT32_FROM_LE (72);
6524         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6525         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6526         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6527         if (assemblyb->entry_point) {
6528                 guint32 table_idx = 0;
6529                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6530                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6531                         table_idx = methodb->table_idx;
6532                 } else {
6533                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6534                 }
6535                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6536         } else {
6537                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6538         }
6539         /* The embedded managed resources */
6540         text_offset = assembly->text_rva + assembly->code.index;
6541         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6542         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6543         text_offset += assembly->resources.index;
6544         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6545         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6546         text_offset += assembly->meta_size;
6547         if (assembly->strong_name_size) {
6548                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6549                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6550                 text_offset += assembly->strong_name_size;
6551         }
6552
6553         /* write the section tables and section content */
6554         section = (MonoSectionTable*)(pefile->data + section_start);
6555         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6556                 static const char section_names [][7] = {
6557                         ".text", ".rsrc", ".reloc"
6558                 };
6559                 if (!assembly->sections [i].size)
6560                         continue;
6561                 strcpy (section->st_name, section_names [i]);
6562                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6563                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6564                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6565                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6566                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6567                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6568                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6569                 section ++;
6570         }
6571         
6572         checked_write_file (file, pefile->data, pefile->index);
6573         
6574         mono_dynamic_stream_reset (pefile);
6575         
6576         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6577                 if (!assembly->sections [i].size)
6578                         continue;
6579                 
6580                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6581                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6582                 
6583                 switch (i) {
6584                 case MONO_SECTION_TEXT:
6585                         /* patch entry point */
6586                         p = (guchar*)(assembly->code.data + 2);
6587                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6588                         *p++ = (value) & 0xff;
6589                         *p++ = (value >> 8) & 0xff;
6590                         *p++ = (value >> 16) & 0xff;
6591                         *p++ = (value >> 24) & 0xff;
6592                 
6593                         checked_write_file (file, assembly->code.data, assembly->code.index);
6594                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6595                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6596                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6597                                 
6598
6599                         g_free (assembly->image.raw_metadata);
6600                         break;
6601                 case MONO_SECTION_RELOC: {
6602                         struct {
6603                                 guint32 page_rva;
6604                                 guint32 block_size;
6605                                 guint16 type_and_offset;
6606                                 guint16 term;
6607                         } reloc;
6608                         
6609                         g_assert (sizeof (reloc) == 12);
6610                         
6611                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6612                         reloc.block_size = GUINT32_FROM_LE (12);
6613                         
6614                         /* 
6615                          * the entrypoint is always at the start of the text section 
6616                          * 3 is IMAGE_REL_BASED_HIGHLOW
6617                          * 2 is patch_size_rva - text_rva
6618                          */
6619                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6620                         reloc.term = 0;
6621                         
6622                         checked_write_file (file, &reloc, sizeof (reloc));
6623                         
6624                         break;
6625                 }
6626                 case MONO_SECTION_RSRC:
6627                         if (assembly->win32_res) {
6628
6629                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6630                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6631                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6632                         }
6633                         break;
6634                 default:
6635                         g_assert_not_reached ();
6636                 }
6637         }
6638         
6639         /* check that the file is properly padded */
6640         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6641                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6642         if (! SetEndOfFile (file))
6643                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6644         
6645         mono_dynamic_stream_reset (&assembly->code);
6646         mono_dynamic_stream_reset (&assembly->us);
6647         mono_dynamic_stream_reset (&assembly->blob);
6648         mono_dynamic_stream_reset (&assembly->guid);
6649         mono_dynamic_stream_reset (&assembly->sheap);
6650
6651         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6652         g_hash_table_destroy (assembly->blob_cache);
6653         assembly->blob_cache = NULL;
6654
6655         return TRUE;
6656 }
6657
6658 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6659
6660 gboolean
6661 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6662 {
6663         g_assert_not_reached ();
6664 }
6665
6666 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6667
6668 #ifndef DISABLE_REFLECTION_EMIT
6669
6670 MonoReflectionModule *
6671 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6672 {
6673         char *name;
6674         MonoImage *image;
6675         MonoImageOpenStatus status;
6676         MonoDynamicAssembly *assembly;
6677         guint32 module_count;
6678         MonoImage **new_modules;
6679         gboolean *new_modules_loaded;
6680         
6681         mono_error_init (error);
6682         
6683         name = mono_string_to_utf8 (fileName);
6684
6685         image = mono_image_open (name, &status);
6686         if (!image) {
6687                 if (status == MONO_IMAGE_ERROR_ERRNO)
6688                         mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6689                 else
6690                         mono_error_set_bad_image_name (error, name, NULL);
6691                 g_free (name);
6692                 return NULL;
6693         }
6694
6695         g_free (name);
6696
6697         assembly = ab->dynamic_assembly;
6698         image->assembly = (MonoAssembly*)assembly;
6699
6700         module_count = image->assembly->image->module_count;
6701         new_modules = g_new0 (MonoImage *, module_count + 1);
6702         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6703
6704         if (image->assembly->image->modules)
6705                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6706         if (image->assembly->image->modules_loaded)
6707                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6708         new_modules [module_count] = image;
6709         new_modules_loaded [module_count] = TRUE;
6710         mono_image_addref (image);
6711
6712         g_free (image->assembly->image->modules);
6713         image->assembly->image->modules = new_modules;
6714         image->assembly->image->modules_loaded = new_modules_loaded;
6715         image->assembly->image->module_count ++;
6716
6717         mono_assembly_load_references (image, &status);
6718         if (status) {
6719                 mono_image_close (image);
6720                 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6721                 return NULL;
6722         }
6723
6724         return mono_module_get_object_checked (mono_domain_get (), image, error);
6725 }
6726
6727 #endif /* DISABLE_REFLECTION_EMIT */
6728
6729 /*
6730  * We need to return always the same object for MethodInfo, FieldInfo etc..
6731  * but we need to consider the reflected type.
6732  * type uses a different hash, since it uses custom hash/equal functions.
6733  */
6734
6735 typedef struct {
6736         gpointer item;
6737         MonoClass *refclass;
6738 } ReflectedEntry;
6739
6740 static gboolean
6741 reflected_equal (gconstpointer a, gconstpointer b) {
6742         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6743         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6744
6745         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6746 }
6747
6748 static guint
6749 reflected_hash (gconstpointer a) {
6750         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6751         return mono_aligned_addr_hash (ea->item);
6752 }
6753
6754 #define CHECK_OBJECT(t,p,k)     \
6755         do {    \
6756                 t _obj; \
6757                 ReflectedEntry e;       \
6758                 e.item = (p);   \
6759                 e.refclass = (k);       \
6760                 mono_domain_lock (domain);      \
6761                 if (!domain->refobject_hash)    \
6762                         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");  \
6763                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6764                         mono_domain_unlock (domain);    \
6765                         return _obj;    \
6766                 }       \
6767         mono_domain_unlock (domain); \
6768         } while (0)
6769
6770 #ifdef HAVE_BOEHM_GC
6771 /* ReflectedEntry doesn't need to be GC tracked */
6772 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6773 #define FREE_REFENTRY(entry) g_free ((entry))
6774 #define REFENTRY_REQUIRES_CLEANUP
6775 #else
6776 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6777 /* FIXME: */
6778 #define FREE_REFENTRY(entry)
6779 #endif
6780
6781 #define CACHE_OBJECT(t,p,o,k)   \
6782         do {    \
6783                 t _obj; \
6784         ReflectedEntry pe; \
6785         pe.item = (p); \
6786         pe.refclass = (k); \
6787         mono_domain_lock (domain); \
6788                 if (!domain->refobject_hash)    \
6789                         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");  \
6790         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6791         if (!_obj) { \
6792                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6793                     e->item = (p);      \
6794                     e->refclass = (k);  \
6795                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6796             _obj = o; \
6797         } \
6798                 mono_domain_unlock (domain);    \
6799         return _obj; \
6800         } while (0)
6801
6802 static void
6803 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6804 {
6805         mono_domain_lock (domain);
6806         if (domain->refobject_hash) {
6807         ReflectedEntry pe;
6808                 gpointer orig_pe, orig_value;
6809
6810                 pe.item = o;
6811                 pe.refclass = klass;
6812                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6813                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6814                         FREE_REFENTRY (orig_pe);
6815                 }
6816         }
6817         mono_domain_unlock (domain);
6818 }
6819
6820 #ifdef REFENTRY_REQUIRES_CLEANUP
6821 static void
6822 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6823 {
6824         FREE_REFENTRY (key);
6825 }
6826 #endif
6827
6828 void
6829 mono_reflection_cleanup_domain (MonoDomain *domain)
6830 {
6831         if (domain->refobject_hash) {
6832 /*let's avoid scanning the whole hashtable if not needed*/
6833 #ifdef REFENTRY_REQUIRES_CLEANUP
6834                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6835 #endif
6836                 mono_g_hash_table_destroy (domain->refobject_hash);
6837                 domain->refobject_hash = NULL;
6838         }
6839 }
6840
6841 #ifndef DISABLE_REFLECTION_EMIT
6842 static gpointer
6843 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6844 {
6845         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6846 }
6847
6848 static gpointer
6849 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6850 {
6851         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6852 }
6853
6854 void
6855 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6856 {
6857         MonoDynamicImage *image = moduleb->dynamic_image;
6858         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6859         if (!image) {
6860                 MonoError error;
6861                 int module_count;
6862                 MonoImage **new_modules;
6863                 MonoImage *ass;
6864                 char *name, *fqname;
6865                 /*
6866                  * FIXME: we already created an image in mono_image_basic_init (), but
6867                  * we don't know which module it belongs to, since that is only 
6868                  * determined at assembly save time.
6869                  */
6870                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6871                 name = mono_string_to_utf8 (ab->name);
6872                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6873                 if (!mono_error_ok (&error)) {
6874                         g_free (name);
6875                         mono_error_raise_exception (&error);
6876                 }
6877                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6878
6879                 moduleb->module.image = &image->image;
6880                 moduleb->dynamic_image = image;
6881                 register_module (mono_object_domain (moduleb), moduleb, image);
6882
6883                 /* register the module with the assembly */
6884                 ass = ab->dynamic_assembly->assembly.image;
6885                 module_count = ass->module_count;
6886                 new_modules = g_new0 (MonoImage *, module_count + 1);
6887
6888                 if (ass->modules)
6889                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6890                 new_modules [module_count] = &image->image;
6891                 mono_image_addref (&image->image);
6892
6893                 g_free (ass->modules);
6894                 ass->modules = new_modules;
6895                 ass->module_count ++;
6896         }
6897 }
6898
6899 void
6900 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6901 {
6902         MonoDynamicImage *image = moduleb->dynamic_image;
6903
6904         g_assert (type->type);
6905         image->wrappers_type = mono_class_from_mono_type (type->type);
6906 }
6907
6908 #endif
6909
6910 /*
6911  * mono_assembly_get_object:
6912  * @domain: an app domain
6913  * @assembly: an assembly
6914  *
6915  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6916  */
6917 MonoReflectionAssembly*
6918 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6919 {
6920         MonoError error;
6921         MonoReflectionAssembly *result;
6922         result = mono_assembly_get_object_checked (domain, assembly, &error);
6923         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6924         return result;
6925 }
6926 /*
6927  * mono_assembly_get_object_checked:
6928  * @domain: an app domain
6929  * @assembly: an assembly
6930  *
6931  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6932  */
6933 MonoReflectionAssembly*
6934 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6935 {
6936         MonoReflectionAssembly *res;
6937         
6938         mono_error_init (error);
6939
6940         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6941         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6942         if (!res)
6943                 return NULL;
6944         res->assembly = assembly;
6945
6946         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6947 }
6948
6949
6950
6951 MonoReflectionModule*   
6952 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6953 {
6954         MonoError error;
6955         MonoReflectionModule *result;
6956         result = mono_module_get_object_checked (domain, image, &error);
6957         mono_error_raise_exception (&error);
6958         return result;
6959 }
6960
6961 MonoReflectionModule*
6962 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6963 {
6964         MonoReflectionModule *res;
6965         char* basename;
6966         
6967         mono_error_init (error);
6968         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6969         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6970         if (!res)
6971                 return NULL;
6972
6973         res->image = image;
6974         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6975         if (!assm_obj)
6976                 return NULL;
6977         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6978
6979         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6980         basename = g_path_get_basename (image->name);
6981         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6982         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6983         
6984         g_free (basename);
6985
6986         if (image->assembly->image == image) {
6987                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6988         } else {
6989                 int i;
6990                 res->token = 0;
6991                 if (image->assembly->image->modules) {
6992                         for (i = 0; i < image->assembly->image->module_count; i++) {
6993                                 if (image->assembly->image->modules [i] == image)
6994                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6995                         }
6996                         g_assert (res->token);
6997                 }
6998         }
6999
7000         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7001 }
7002
7003 MonoReflectionModule*
7004 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7005 {
7006         MonoError error;
7007         MonoReflectionModule *result;
7008         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7009         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7010         return result;
7011 }
7012
7013 MonoReflectionModule*
7014 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7015 {
7016         MonoReflectionModule *res;
7017         MonoTableInfo *table;
7018         guint32 cols [MONO_FILE_SIZE];
7019         const char *name;
7020         guint32 i, name_idx;
7021         const char *val;
7022         
7023         mono_error_init (error);
7024
7025         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7026         if (!res)
7027                 return NULL;
7028
7029         table = &image->tables [MONO_TABLE_FILE];
7030         g_assert (table_index < table->rows);
7031         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7032
7033         res->image = NULL;
7034         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7035         if (!assm_obj)
7036                 return NULL;
7037         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7038         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7039
7040         /* Check whenever the row has a corresponding row in the moduleref table */
7041         table = &image->tables [MONO_TABLE_MODULEREF];
7042         for (i = 0; i < table->rows; ++i) {
7043                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7044                 val = mono_metadata_string_heap (image, name_idx);
7045                 if (strcmp (val, name) == 0)
7046                         res->image = image->modules [i];
7047         }
7048
7049         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7050         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7051         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7052         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7053         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7054
7055         return res;
7056 }
7057
7058 static gboolean
7059 verify_safe_for_managed_space (MonoType *type)
7060 {
7061         switch (type->type) {
7062 #ifdef DEBUG_HARDER
7063         case MONO_TYPE_ARRAY:
7064                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7065         case MONO_TYPE_PTR:
7066                 return verify_safe_for_managed_space (type->data.type);
7067         case MONO_TYPE_SZARRAY:
7068                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7069         case MONO_TYPE_GENERICINST: {
7070                 MonoGenericInst *inst = type->data.generic_class->inst;
7071                 int i;
7072                 if (!inst->is_open)
7073                         break;
7074                 for (i = 0; i < inst->type_argc; ++i)
7075                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7076                                 return FALSE;
7077                 return TRUE;
7078         }
7079 #endif
7080         case MONO_TYPE_VAR:
7081         case MONO_TYPE_MVAR:
7082                 return TRUE;
7083         default:
7084                 return TRUE;
7085         }
7086 }
7087
7088 static MonoType*
7089 mono_type_normalize (MonoType *type)
7090 {
7091         int i;
7092         MonoGenericClass *gclass;
7093         MonoGenericInst *ginst;
7094         MonoClass *gtd;
7095         MonoGenericContainer *gcontainer;
7096         MonoType **argv = NULL;
7097         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7098
7099         if (type->type != MONO_TYPE_GENERICINST)
7100                 return type;
7101
7102         gclass = type->data.generic_class;
7103         ginst = gclass->context.class_inst;
7104         if (!ginst->is_open)
7105                 return type;
7106
7107         gtd = gclass->container_class;
7108         gcontainer = gtd->generic_container;
7109         argv = g_newa (MonoType*, ginst->type_argc);
7110
7111         for (i = 0; i < ginst->type_argc; ++i) {
7112                 MonoType *t = ginst->type_argv [i], *norm;
7113                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7114                         is_denorm_gtd = FALSE;
7115                 norm = mono_type_normalize (t);
7116                 argv [i] = norm;
7117                 if (norm != t)
7118                         requires_rebind = TRUE;
7119         }
7120
7121         if (is_denorm_gtd)
7122                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7123
7124         if (requires_rebind) {
7125                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7126                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7127         }
7128
7129         return type;
7130 }
7131 /*
7132  * mono_type_get_object:
7133  * @domain: an app domain
7134  * @type: a type
7135  *
7136  * Return an System.MonoType object representing the type @type.
7137  */
7138 MonoReflectionType*
7139 mono_type_get_object (MonoDomain *domain, MonoType *type)
7140 {
7141         MonoError error;
7142         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7143         mono_error_raise_exception (&error);
7144
7145         return ret;
7146 }
7147
7148 MonoReflectionType*
7149 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7150 {
7151         MonoType *norm_type;
7152         MonoReflectionType *res;
7153         MonoClass *klass;
7154
7155         mono_error_init (error);
7156
7157         klass = mono_class_from_mono_type (type);
7158
7159         /*we must avoid using @type as it might have come
7160          * from a mono_metadata_type_dup and the caller
7161          * expects that is can be freed.
7162          * Using the right type from 
7163          */
7164         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7165
7166         /* void is very common */
7167         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7168                 return (MonoReflectionType*)domain->typeof_void;
7169
7170         /*
7171          * If the vtable of the given class was already created, we can use
7172          * the MonoType from there and avoid all locking and hash table lookups.
7173          * 
7174          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7175          * that the resulting object is different.   
7176          */
7177         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7178                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7179                 if (vtable && vtable->type)
7180                         return (MonoReflectionType *)vtable->type;
7181         }
7182
7183         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7184         mono_domain_lock (domain);
7185         if (!domain->type_hash)
7186                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7187                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7188         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7189                 mono_domain_unlock (domain);
7190                 mono_loader_unlock ();
7191                 return res;
7192         }
7193
7194         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7195          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7196          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7197          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7198          * artifact of how generics are encoded and should be transparent to managed code so we
7199          * need to weed out this diference when retrieving managed System.Type objects.
7200          */
7201         norm_type = mono_type_normalize (type);
7202         if (norm_type != type) {
7203                 res = mono_type_get_object_checked (domain, norm_type, error);
7204                 if (!mono_error_ok (error))
7205                         return NULL;
7206                 mono_g_hash_table_insert (domain->type_hash, type, res);
7207                 mono_domain_unlock (domain);
7208                 mono_loader_unlock ();
7209                 return res;
7210         }
7211
7212         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7213         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7214                 g_assert (0);
7215
7216         if (!verify_safe_for_managed_space (type)) {
7217                 mono_domain_unlock (domain);
7218                 mono_loader_unlock ();
7219                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7220                 return NULL;
7221         }
7222
7223         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7224                 gboolean is_type_done = TRUE;
7225                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7226                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7227                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7228                 */
7229                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7230                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7231
7232                         if (gparam->owner && gparam->owner->is_method) {
7233                                 MonoMethod *method = gparam->owner->owner.method;
7234                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7235                                         is_type_done = FALSE;
7236                         } else if (gparam->owner && !gparam->owner->is_method) {
7237                                 MonoClass *klass = gparam->owner->owner.klass;
7238                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7239                                         is_type_done = FALSE;
7240                         }
7241                 } 
7242
7243                 /* g_assert_not_reached (); */
7244                 /* should this be considered an error condition? */
7245                 if (is_type_done && !type->byref) {
7246                         mono_domain_unlock (domain);
7247                         mono_loader_unlock ();
7248                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7249                 }
7250         }
7251         /* This is stored in vtables/JITted code so it has to be pinned */
7252         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7253         if (!mono_error_ok (error))
7254                 return NULL;
7255
7256         res->type = type;
7257         mono_g_hash_table_insert (domain->type_hash, type, res);
7258
7259         if (type->type == MONO_TYPE_VOID)
7260                 domain->typeof_void = (MonoObject*)res;
7261
7262         mono_domain_unlock (domain);
7263         mono_loader_unlock ();
7264         return res;
7265 }
7266
7267 /*
7268  * mono_method_get_object:
7269  * @domain: an app domain
7270  * @method: a method
7271  * @refclass: the reflected type (can be NULL)
7272  *
7273  * Return an System.Reflection.MonoMethod object representing the method @method.
7274  */
7275 MonoReflectionMethod*
7276 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7277 {
7278         MonoError error;
7279         MonoReflectionMethod *ret = NULL;
7280         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7281         mono_error_raise_exception (&error);
7282         return ret;
7283 }
7284
7285 /*
7286  * mono_method_get_object_checked:
7287  * @domain: an app domain
7288  * @method: a method
7289  * @refclass: the reflected type (can be NULL)
7290  * @error: set on error.
7291  *
7292  * Return an System.Reflection.MonoMethod object representing the method @method.
7293  * Returns NULL and sets @error on error.
7294  */
7295 MonoReflectionMethod*
7296 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7297 {
7298         /*
7299          * We use the same C representation for methods and constructors, but the type 
7300          * name in C# is different.
7301          */
7302         MonoReflectionType *rt;
7303         MonoClass *klass;
7304         MonoReflectionMethod *ret;
7305
7306         mono_error_init (error);
7307
7308         if (method->is_inflated) {
7309                 MonoReflectionGenericMethod *gret;
7310
7311                 if (!refclass)
7312                         refclass = method->klass;
7313                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7314                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7315                         klass = mono_class_get_mono_generic_cmethod_class ();
7316                 } else {
7317                         klass = mono_class_get_mono_generic_method_class ();
7318                 }
7319                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7320                 if (!mono_error_ok (error))
7321                         goto leave;
7322                 gret->method.method = method;
7323
7324                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7325
7326                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7327                 if (!mono_error_ok (error))
7328                     goto leave;
7329
7330                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7331
7332                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7333         }
7334
7335         if (!refclass)
7336                 refclass = method->klass;
7337
7338         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7339         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7340                 klass = mono_class_get_mono_cmethod_class ();
7341         }
7342         else {
7343                 klass = mono_class_get_mono_method_class ();
7344         }
7345         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7346         if (!mono_error_ok (error))
7347                 goto leave;
7348         ret->method = method;
7349
7350         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7351         if (!mono_error_ok (error))
7352                 goto leave;
7353
7354         MONO_OBJECT_SETREF (ret, reftype, rt);
7355
7356         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7357
7358 leave:
7359         g_assert (!mono_error_ok (error));
7360         return NULL;
7361 }
7362
7363 /*
7364  * mono_method_clear_object:
7365  *
7366  *   Clear the cached reflection objects for the dynamic method METHOD.
7367  */
7368 void
7369 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7370 {
7371         MonoClass *klass;
7372         g_assert (method_is_dynamic (method));
7373
7374         klass = method->klass;
7375         while (klass) {
7376                 clear_cached_object (domain, method, klass);
7377                 klass = klass->parent;
7378         }
7379         /* Added by mono_param_get_objects () */
7380         clear_cached_object (domain, &(method->signature), NULL);
7381         klass = method->klass;
7382         while (klass) {
7383                 clear_cached_object (domain, &(method->signature), klass);
7384                 klass = klass->parent;
7385         }
7386 }
7387
7388 /*
7389  * mono_field_get_object:
7390  * @domain: an app domain
7391  * @klass: a type
7392  * @field: a field
7393  *
7394  * Return an System.Reflection.MonoField object representing the field @field
7395  * in class @klass.
7396  */
7397 MonoReflectionField*
7398 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7399 {
7400         MonoError error;
7401         MonoReflectionField *result;
7402         result = mono_field_get_object_checked (domain, klass, field, &error);
7403         mono_error_raise_exception (&error);
7404         return result;
7405 }
7406
7407 /*
7408  * mono_field_get_object_checked:
7409  * @domain: an app domain
7410  * @klass: a type
7411  * @field: a field
7412  * @error: set on error
7413  *
7414  * Return an System.Reflection.MonoField object representing the field @field
7415  * in class @klass. On error, returns NULL and sets @error.
7416  */
7417 MonoReflectionField*
7418 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7419 {
7420         MonoReflectionType *rt;
7421         MonoReflectionField *res;
7422
7423         mono_error_init (error);
7424
7425         CHECK_OBJECT (MonoReflectionField *, field, klass);
7426         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7427         if (!res)
7428                 return NULL;
7429         res->klass = klass;
7430         res->field = field;
7431         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7432
7433         if (is_field_on_inst (field)) {
7434                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7435
7436                 rt = mono_type_get_object_checked (domain, field->type, error);
7437                 if (!mono_error_ok (error))
7438                         return NULL;
7439
7440                 MONO_OBJECT_SETREF (res, type, rt);
7441         } else {
7442                 if (field->type) {
7443                         rt = mono_type_get_object_checked (domain, field->type, error);
7444                         if (!mono_error_ok (error))
7445                                 return NULL;
7446
7447                         MONO_OBJECT_SETREF (res, type, rt);
7448                 }
7449                 res->attrs = mono_field_get_flags (field);
7450         }
7451         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7452 }
7453
7454 /*
7455  * mono_property_get_object:
7456  * @domain: an app domain
7457  * @klass: a type
7458  * @property: a property
7459  *
7460  * Return an System.Reflection.MonoProperty object representing the property @property
7461  * in class @klass.
7462  */
7463 MonoReflectionProperty*
7464 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7465 {
7466         MonoError error;
7467         MonoReflectionProperty *result;
7468         result = mono_property_get_object_checked (domain, klass, property, &error);
7469         mono_error_raise_exception (&error);
7470         return result;
7471 }
7472
7473 /**
7474  * mono_property_get_object:
7475  * @domain: an app domain
7476  * @klass: a type
7477  * @property: a property
7478  * @error: set on error
7479  *
7480  * Return an System.Reflection.MonoProperty object representing the property @property
7481  * in class @klass.  On error returns NULL and sets @error.
7482  */
7483 MonoReflectionProperty*
7484 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7485 {
7486         MonoReflectionProperty *res;
7487
7488         mono_error_init (error);
7489
7490         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7491         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7492         if (!res)
7493                 return NULL;
7494         res->klass = klass;
7495         res->property = property;
7496         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7497 }
7498
7499 /*
7500  * mono_event_get_object:
7501  * @domain: an app domain
7502  * @klass: a type
7503  * @event: a event
7504  *
7505  * Return an System.Reflection.MonoEvent object representing the event @event
7506  * in class @klass.
7507  */
7508 MonoReflectionEvent*
7509 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7510 {
7511         MonoError error;
7512         MonoReflectionEvent *result;
7513         result = mono_event_get_object_checked (domain, klass, event, &error);
7514         mono_error_raise_exception (&error);
7515         return result;
7516 }
7517
7518 /**
7519  * mono_event_get_object_checked:
7520  * @domain: an app domain
7521  * @klass: a type
7522  * @event: a event
7523  * @error: set on error
7524  *
7525  * Return an System.Reflection.MonoEvent object representing the event @event
7526  * in class @klass. On failure sets @error and returns NULL
7527  */
7528 MonoReflectionEvent*
7529 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7530 {
7531         MonoReflectionEvent *res;
7532         MonoReflectionMonoEvent *mono_event;
7533
7534         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7535         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7536         if (!mono_event)
7537                 return NULL;
7538         mono_event->klass = klass;
7539         mono_event->event = event;
7540         res = (MonoReflectionEvent*)mono_event;
7541         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7542 }
7543
7544 /**
7545  * mono_get_reflection_missing_object:
7546  * @domain: Domain where the object lives
7547  *
7548  * Returns the System.Reflection.Missing.Value singleton object
7549  * (of type System.Reflection.Missing).
7550  *
7551  * Used as the value for ParameterInfo.DefaultValue when Optional
7552  * is present
7553  */
7554 static MonoObject *
7555 mono_get_reflection_missing_object (MonoDomain *domain)
7556 {
7557         MonoError error;
7558         MonoObject *obj;
7559         static MonoClassField *missing_value_field = NULL;
7560         
7561         if (!missing_value_field) {
7562                 MonoClass *missing_klass;
7563                 missing_klass = mono_class_get_missing_class ();
7564                 mono_class_init (missing_klass);
7565                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7566                 g_assert (missing_value_field);
7567         }
7568         obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7569         mono_error_assert_ok (&error);
7570         return obj;
7571 }
7572
7573 static MonoObject*
7574 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7575 {
7576         if (!*dbnull)
7577                 *dbnull = mono_get_dbnull_object (domain);
7578         return *dbnull;
7579 }
7580
7581 static MonoObject*
7582 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7583 {
7584         if (!*reflection_missing)
7585                 *reflection_missing = mono_get_reflection_missing_object (domain);
7586         return *reflection_missing;
7587 }
7588
7589 /*
7590  * mono_param_get_objects:
7591  * @domain: an app domain
7592  * @method: a method
7593  *
7594  * Return an System.Reflection.ParameterInfo array object representing the parameters
7595  * in the method @method.
7596  */
7597 MonoArray*
7598 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7599 {
7600         static MonoClass *System_Reflection_ParameterInfo;
7601         static MonoClass *System_Reflection_ParameterInfo_array;
7602         MonoArray *res = NULL;
7603         MonoReflectionMethod *member = NULL;
7604         MonoReflectionParameter *param = NULL;
7605         char **names = NULL, **blobs = NULL;
7606         guint32 *types = NULL;
7607         MonoType *type = NULL;
7608         MonoObject *dbnull = NULL;
7609         MonoObject *missing = NULL;
7610         MonoMarshalSpec **mspecs = NULL;
7611         MonoMethodSignature *sig = NULL;
7612         MonoVTable *pinfo_vtable;
7613         MonoReflectionType *rt;
7614         int i;
7615
7616         mono_error_init (error);
7617         
7618         if (!System_Reflection_ParameterInfo_array) {
7619                 MonoClass *klass;
7620
7621                 klass = mono_class_get_mono_parameter_info_class ();
7622
7623                 mono_memory_barrier ();
7624                 System_Reflection_ParameterInfo = klass; 
7625
7626         
7627                 klass = mono_array_class_get (klass, 1);
7628                 mono_memory_barrier ();
7629                 System_Reflection_ParameterInfo_array = klass;
7630         }
7631
7632         sig = mono_method_signature_checked (method, error);
7633         if (!mono_error_ok (error))
7634                 goto leave;
7635
7636         if (!sig->param_count) {
7637                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7638                 if (!res)
7639                         goto leave;
7640
7641                 return res;
7642         }
7643
7644         /* Note: the cache is based on the address of the signature into the method
7645          * since we already cache MethodInfos with the method as keys.
7646          */
7647         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7648
7649         member = mono_method_get_object_checked (domain, method, refclass, error);
7650         if (!member)
7651                 goto leave;
7652         names = g_new (char *, sig->param_count);
7653         mono_method_get_param_names (method, (const char **) names);
7654
7655         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7656         mono_method_get_marshal_info (method, mspecs);
7657
7658         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7659         if (!res)
7660                 goto leave;
7661
7662         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7663         for (i = 0; i < sig->param_count; ++i) {
7664                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7665                 if (!param)
7666                         goto leave;
7667
7668                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7669                 if (!rt)
7670                         goto leave;
7671
7672                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7673
7674                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7675
7676                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7677
7678                 param->PositionImpl = i;
7679                 param->AttrsImpl = sig->params [i]->attrs;
7680
7681                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7682                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7683                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7684                         else
7685                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7686                 } else {
7687
7688                         if (!blobs) {
7689                                 blobs = g_new0 (char *, sig->param_count);
7690                                 types = g_new0 (guint32, sig->param_count);
7691                                 get_default_param_value_blobs (method, blobs, types); 
7692                         }
7693
7694                         /* Build MonoType for the type from the Constant Table */
7695                         if (!type)
7696                                 type = g_new0 (MonoType, 1);
7697                         type->type = (MonoTypeEnum)types [i];
7698                         type->data.klass = NULL;
7699                         if (types [i] == MONO_TYPE_CLASS)
7700                                 type->data.klass = mono_defaults.object_class;
7701                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7702                                 /* For enums, types [i] contains the base type */
7703
7704                                         type->type = MONO_TYPE_VALUETYPE;
7705                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7706                         } else
7707                                 type->data.klass = mono_class_from_mono_type (type);
7708
7709                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7710                         if (!is_ok (error))
7711                                 goto leave;
7712                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7713
7714                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7715                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7716                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7717                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7718                                 else
7719                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7720                         }
7721                         
7722                 }
7723
7724                 if (mspecs [i + 1]) {
7725                         MonoReflectionMarshalAsAttribute* mobj;
7726                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7727                         if (!mobj)
7728                                 goto leave;
7729                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7730                 }
7731                 
7732                 mono_array_setref (res, i, param);
7733         }
7734
7735 leave:
7736         g_free (names);
7737         g_free (blobs);
7738         g_free (types);
7739         g_free (type);
7740
7741         if (sig) {
7742                 for (i = sig->param_count; i >= 0; i--) {
7743                         if (mspecs [i])
7744                                 mono_metadata_free_marshal_spec (mspecs [i]);
7745                 }
7746         }
7747         g_free (mspecs);
7748
7749         if (!is_ok (error))
7750                 return NULL;
7751         
7752         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7753 }
7754
7755 MonoArray*
7756 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7757 {
7758         MonoError error;
7759         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7760         mono_error_assert_ok (&error);
7761         return result;
7762 }
7763
7764 /*
7765  * mono_method_body_get_object:
7766  * @domain: an app domain
7767  * @method: a method
7768  *
7769  * Return an System.Reflection.MethodBody object representing the method @method.
7770  */
7771 MonoReflectionMethodBody*
7772 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7773 {
7774         MonoError error;
7775         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7776         mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
7777         return result;
7778 }
7779
7780 /**
7781  * mono_method_body_get_object_checked:
7782  * @domain: an app domain
7783  * @method: a method
7784  * @error: set on error
7785  *
7786  * Return an System.Reflection.MethodBody object representing the
7787  * method @method.  On failure, returns NULL and sets @error.
7788  */
7789 MonoReflectionMethodBody*
7790 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7791 {
7792         MonoReflectionMethodBody *ret;
7793         MonoMethodHeader *header;
7794         MonoImage *image;
7795         MonoReflectionType *rt;
7796         guint32 method_rva, local_var_sig_token;
7797         char *ptr;
7798         unsigned char format, flags;
7799         int i;
7800
7801         mono_error_init (error);
7802
7803         /* for compatibility with .net */
7804         if (method_is_dynamic (method)) {
7805                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7806                 return NULL;
7807         }
7808
7809         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7810
7811         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7812                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7813             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7814                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7815             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7816                 return NULL;
7817
7818         image = method->klass->image;
7819         header = mono_method_get_header_checked (method, error);
7820         return_val_if_nok (error, NULL);
7821
7822         if (!image_is_dynamic (image)) {
7823                 /* Obtain local vars signature token */
7824                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7825                 ptr = mono_image_rva_map (image, method_rva);
7826                 flags = *(const unsigned char *) ptr;
7827                 format = flags & METHOD_HEADER_FORMAT_MASK;
7828                 switch (format){
7829                 case METHOD_HEADER_TINY_FORMAT:
7830                         local_var_sig_token = 0;
7831                         break;
7832                 case METHOD_HEADER_FAT_FORMAT:
7833                         ptr += 2;
7834                         ptr += 2;
7835                         ptr += 4;
7836                         local_var_sig_token = read32 (ptr);
7837                         break;
7838                 default:
7839                         g_assert_not_reached ();
7840                 }
7841         } else
7842                 local_var_sig_token = 0; //FIXME
7843
7844         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7845         if (!is_ok (error))
7846                 goto fail;
7847
7848         ret->init_locals = header->init_locals;
7849         ret->max_stack = header->max_stack;
7850         ret->local_var_sig_token = local_var_sig_token;
7851         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7852         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7853
7854         /* Locals */
7855         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7856         for (i = 0; i < header->num_locals; ++i) {
7857                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7858                 if (!is_ok (error))
7859                         goto fail;
7860
7861                 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7862                 if (!is_ok (error))
7863                         goto fail;
7864
7865                 MONO_OBJECT_SETREF (info, local_type, rt);
7866
7867                 info->is_pinned = header->locals [i]->pinned;
7868                 info->local_index = i;
7869                 mono_array_setref (ret->locals, i, info);
7870         }
7871
7872         /* Exceptions */
7873         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7874         for (i = 0; i < header->num_clauses; ++i) {
7875                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7876                 if (!is_ok (error))
7877                         goto fail;
7878                 MonoExceptionClause *clause = &header->clauses [i];
7879
7880                 info->flags = clause->flags;
7881                 info->try_offset = clause->try_offset;
7882                 info->try_length = clause->try_len;
7883                 info->handler_offset = clause->handler_offset;
7884                 info->handler_length = clause->handler_len;
7885                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7886                         info->filter_offset = clause->data.filter_offset;
7887                 else if (clause->data.catch_class) {
7888                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7889                         if (!is_ok (error))
7890                                 goto fail;
7891
7892                         MONO_OBJECT_SETREF (info, catch_type, rt);
7893                 }
7894
7895                 mono_array_setref (ret->clauses, i, info);
7896         }
7897
7898         mono_metadata_free_mh (header);
7899         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7900         return ret;
7901
7902 fail:
7903         mono_metadata_free_mh (header);
7904         return NULL;
7905 }
7906
7907 /**
7908  * mono_get_dbnull_object:
7909  * @domain: Domain where the object lives
7910  *
7911  * Returns the System.DBNull.Value singleton object
7912  *
7913  * Used as the value for ParameterInfo.DefaultValue 
7914  */
7915 MonoObject *
7916 mono_get_dbnull_object (MonoDomain *domain)
7917 {
7918         MonoError error;
7919         MonoObject *obj;
7920         static MonoClassField *dbnull_value_field = NULL;
7921         
7922         if (!dbnull_value_field) {
7923                 MonoClass *dbnull_klass;
7924                 dbnull_klass = mono_class_get_dbnull_class ();
7925                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7926                 g_assert (dbnull_value_field);
7927         }
7928         obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
7929         mono_error_assert_ok (&error);
7930         return obj;
7931 }
7932
7933 static void
7934 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7935 {
7936         guint32 param_index, i, lastp, crow = 0;
7937         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7938         gint32 idx;
7939
7940         MonoClass *klass = method->klass;
7941         MonoImage *image = klass->image;
7942         MonoMethodSignature *methodsig = mono_method_signature (method);
7943
7944         MonoTableInfo *constt;
7945         MonoTableInfo *methodt;
7946         MonoTableInfo *paramt;
7947
7948         if (!methodsig->param_count)
7949                 return;
7950
7951         mono_class_init (klass);
7952
7953         if (image_is_dynamic (klass->image)) {
7954                 MonoReflectionMethodAux *aux;
7955                 if (method->is_inflated)
7956                         method = ((MonoMethodInflated*)method)->declaring;
7957                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7958                 if (aux && aux->param_defaults) {
7959                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7960                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7961                 }
7962                 return;
7963         }
7964
7965         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7966         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7967         constt = &image->tables [MONO_TABLE_CONSTANT];
7968
7969         idx = mono_method_get_index (method) - 1;
7970         g_assert (idx != -1);
7971
7972         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7973         if (idx + 1 < methodt->rows)
7974                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7975         else
7976                 lastp = paramt->rows + 1;
7977
7978         for (i = param_index; i < lastp; ++i) {
7979                 guint32 paramseq;
7980
7981                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7982                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7983
7984                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7985                         continue;
7986
7987                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7988                 if (!crow) {
7989                         continue;
7990                 }
7991         
7992                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7993                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7994                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7995         }
7996
7997         return;
7998 }
7999
8000 MonoObject *
8001 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8002 {
8003         void *retval;
8004         MonoClass *klass;
8005         MonoObject *object;
8006         MonoType *basetype = type;
8007
8008         mono_error_init (error);
8009
8010         if (!blob)
8011                 return NULL;
8012         
8013         klass = mono_class_from_mono_type (type);
8014         if (klass->valuetype) {
8015                 object = mono_object_new_checked (domain, klass, error);
8016                 return_val_if_nok (error, NULL);
8017                 retval = ((gchar *) object + sizeof (MonoObject));
8018                 if (klass->enumtype)
8019                         basetype = mono_class_enum_basetype (klass);
8020         } else {
8021                 retval = &object;
8022         }
8023                         
8024         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
8025                 return object;
8026         else
8027                 return NULL;
8028 }
8029
8030 static int
8031 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8032         int found_sep;
8033         char *s;
8034         gboolean quoted = FALSE;
8035
8036         memset (assembly, 0, sizeof (MonoAssemblyName));
8037         assembly->culture = "";
8038         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8039
8040         if (*p == '"') {
8041                 quoted = TRUE;
8042                 p++;
8043         }
8044         assembly->name = p;
8045         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8046                 p++;
8047         if (quoted) {
8048                 if (*p != '"')
8049                         return 1;
8050                 *p = 0;
8051                 p++;
8052         }
8053         if (*p != ',')
8054                 return 1;
8055         *p = 0;
8056         /* Remove trailing whitespace */
8057         s = p - 1;
8058         while (*s && g_ascii_isspace (*s))
8059                 *s-- = 0;
8060         p ++;
8061         while (g_ascii_isspace (*p))
8062                 p++;
8063         while (*p) {
8064                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8065                         p += 8;
8066                         assembly->major = strtoul (p, &s, 10);
8067                         if (s == p || *s != '.')
8068                                 return 1;
8069                         p = ++s;
8070                         assembly->minor = strtoul (p, &s, 10);
8071                         if (s == p || *s != '.')
8072                                 return 1;
8073                         p = ++s;
8074                         assembly->build = strtoul (p, &s, 10);
8075                         if (s == p || *s != '.')
8076                                 return 1;
8077                         p = ++s;
8078                         assembly->revision = strtoul (p, &s, 10);
8079                         if (s == p)
8080                                 return 1;
8081                         p = s;
8082                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8083                         p += 8;
8084                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8085                                 assembly->culture = "";
8086                                 p += 7;
8087                         } else {
8088                                 assembly->culture = p;
8089                                 while (*p && *p != ',') {
8090                                         p++;
8091                                 }
8092                         }
8093                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8094                         p += 15;
8095                         if (strncmp (p, "null", 4) == 0) {
8096                                 p += 4;
8097                         } else {
8098                                 int len;
8099                                 gchar *start = p;
8100                                 while (*p && *p != ',') {
8101                                         p++;
8102                                 }
8103                                 len = (p - start + 1);
8104                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8105                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8106                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8107                         }
8108                 } else {
8109                         while (*p && *p != ',')
8110                                 p++;
8111                 }
8112                 found_sep = 0;
8113                 while (g_ascii_isspace (*p) || *p == ',') {
8114                         *p++ = 0;
8115                         found_sep = 1;
8116                         continue;
8117                 }
8118                 /* failed */
8119                 if (!found_sep)
8120                         return 1;
8121         }
8122
8123         return 0;
8124 }
8125
8126 /*
8127  * mono_reflection_parse_type:
8128  * @name: type name
8129  *
8130  * Parse a type name as accepted by the GetType () method and output the info
8131  * extracted in the info structure.
8132  * the name param will be mangled, so, make a copy before passing it to this function.
8133  * The fields in info will be valid until the memory pointed to by name is valid.
8134  *
8135  * See also mono_type_get_name () below.
8136  *
8137  * Returns: 0 on parse error.
8138  */
8139 static int
8140 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8141                              MonoTypeNameParse *info)
8142 {
8143         char *start, *p, *w, *last_point, *startn;
8144         int in_modifiers = 0;
8145         int isbyref = 0, rank = 0, isptr = 0;
8146
8147         start = p = w = name;
8148
8149         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8150         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8151         info->name = info->name_space = NULL;
8152         info->nested = NULL;
8153         info->modifiers = NULL;
8154         info->type_arguments = NULL;
8155
8156         /* last_point separates the namespace from the name */
8157         last_point = NULL;
8158         /* Skips spaces */
8159         while (*p == ' ') p++, start++, w++, name++;
8160
8161         while (*p) {
8162                 switch (*p) {
8163                 case '+':
8164                         *p = 0; /* NULL terminate the name */
8165                         startn = p + 1;
8166                         info->nested = g_list_append (info->nested, startn);
8167                         /* we have parsed the nesting namespace + name */
8168                         if (info->name)
8169                                 break;
8170                         if (last_point) {
8171                                 info->name_space = start;
8172                                 *last_point = 0;
8173                                 info->name = last_point + 1;
8174                         } else {
8175                                 info->name_space = (char *)"";
8176                                 info->name = start;
8177                         }
8178                         break;
8179                 case '.':
8180                         last_point = p;
8181                         break;
8182                 case '\\':
8183                         ++p;
8184                         break;
8185                 case '&':
8186                 case '*':
8187                 case '[':
8188                 case ',':
8189                 case ']':
8190                         in_modifiers = 1;
8191                         break;
8192                 default:
8193                         break;
8194                 }
8195                 if (in_modifiers)
8196                         break;
8197                 // *w++ = *p++;
8198                 p++;
8199         }
8200         
8201         if (!info->name) {
8202                 if (last_point) {
8203                         info->name_space = start;
8204                         *last_point = 0;
8205                         info->name = last_point + 1;
8206                 } else {
8207                         info->name_space = (char *)"";
8208                         info->name = start;
8209                 }
8210         }
8211         while (*p) {
8212                 switch (*p) {
8213                 case '&':
8214                         if (isbyref) /* only one level allowed by the spec */
8215                                 return 0;
8216                         isbyref = 1;
8217                         isptr = 0;
8218                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8219                         *p++ = 0;
8220                         break;
8221                 case '*':
8222                         if (isbyref) /* pointer to ref not okay */
8223                                 return 0;
8224                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8225                         isptr = 1;
8226                         *p++ = 0;
8227                         break;
8228                 case '[':
8229                         if (isbyref) /* array of ref and generic ref are not okay */
8230                                 return 0;
8231                         //Decide if it's an array of a generic argument list
8232                         *p++ = 0;
8233
8234                         if (!*p) //XXX test
8235                                 return 0;
8236                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8237                                 isptr = 0;
8238                                 rank = 1;
8239                                 while (*p) {
8240                                         if (*p == ']')
8241                                                 break;
8242                                         if (*p == ',')
8243                                                 rank++;
8244                                         else if (*p == '*') /* '*' means unknown lower bound */
8245                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8246                                         else
8247                                                 return 0;
8248                                         ++p;
8249                                 }
8250                                 if (*p++ != ']')
8251                                         return 0;
8252                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8253                         } else {
8254                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8255                                         return 0;
8256                                 isptr = 0;
8257                                 info->type_arguments = g_ptr_array_new ();
8258                                 while (*p) {
8259                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8260                                         gboolean fqname = FALSE;
8261
8262                                         g_ptr_array_add (info->type_arguments, subinfo);
8263
8264                                         while (*p == ' ') p++;
8265                                         if (*p == '[') {
8266                                                 p++;
8267                                                 fqname = TRUE;
8268                                         }
8269
8270                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8271                                                 return 0;
8272
8273                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8274                                         if (fqname && (*p != ']')) {
8275                                                 char *aname;
8276
8277                                                 if (*p != ',')
8278                                                         return 0;
8279                                                 *p++ = 0;
8280
8281                                                 aname = p;
8282                                                 while (*p && (*p != ']'))
8283                                                         p++;
8284
8285                                                 if (*p != ']')
8286                                                         return 0;
8287
8288                                                 *p++ = 0;
8289                                                 while (*aname) {
8290                                                         if (g_ascii_isspace (*aname)) {
8291                                                                 ++aname;
8292                                                                 continue;
8293                                                         }
8294                                                         break;
8295                                                 }
8296                                                 if (!*aname ||
8297                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8298                                                         return 0;
8299                                         } else if (fqname && (*p == ']')) {
8300                                                 *p++ = 0;
8301                                         }
8302                                         if (*p == ']') {
8303                                                 *p++ = 0;
8304                                                 break;
8305                                         } else if (!*p) {
8306                                                 return 0;
8307                                         }
8308                                         *p++ = 0;
8309                                 }
8310                         }
8311                         break;
8312                 case ']':
8313                         if (is_recursed)
8314                                 goto end;
8315                         return 0;
8316                 case ',':
8317                         if (is_recursed)
8318                                 goto end;
8319                         *p++ = 0;
8320                         while (*p) {
8321                                 if (g_ascii_isspace (*p)) {
8322                                         ++p;
8323                                         continue;
8324                                 }
8325                                 break;
8326                         }
8327                         if (!*p)
8328                                 return 0; /* missing assembly name */
8329                         if (!assembly_name_to_aname (&info->assembly, p))
8330                                 return 0;
8331                         break;
8332                 default:
8333                         return 0;
8334                 }
8335                 if (info->assembly.name)
8336                         break;
8337         }
8338         // *w = 0; /* terminate class name */
8339  end:
8340         if (!info->name || !*info->name)
8341                 return 0;
8342         if (endptr)
8343                 *endptr = p;
8344         /* add other consistency checks */
8345         return 1;
8346 }
8347
8348
8349 /**
8350  * mono_identifier_unescape_type_name_chars:
8351  * @identifier: the display name of a mono type
8352  *
8353  * Returns:
8354  *  The name in internal form, that is without escaping backslashes.
8355  *
8356  *  The string is modified in place!
8357  */
8358 char*
8359 mono_identifier_unescape_type_name_chars(char* identifier)
8360 {
8361         char *w, *r;
8362         if (!identifier)
8363                 return NULL;
8364         for (w = r = identifier; *r != 0; r++)
8365         {
8366                 char c = *r;
8367                 if (c == '\\') {
8368                         r++;
8369                         if (*r == 0)
8370                                 break;
8371                         c = *r;
8372                 }
8373                 *w = c;
8374                 w++;
8375         }
8376         if (w != r)
8377                 *w = 0;
8378         return identifier;
8379 }
8380
8381 void
8382 mono_identifier_unescape_info (MonoTypeNameParse* info);
8383
8384 static void
8385 unescape_each_type_argument(void* data, void* user_data)
8386 {
8387         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8388         mono_identifier_unescape_info (info);
8389 }
8390
8391 static void
8392 unescape_each_nested_name (void* data, void* user_data)
8393 {
8394         char* nested_name = (char*) data;
8395         mono_identifier_unescape_type_name_chars(nested_name);
8396 }
8397
8398 /**
8399  * mono_identifier_unescape_info:
8400  *
8401  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8402  *
8403  * Returns: nothing.
8404  *
8405  * Destructively updates the info by unescaping the identifiers that
8406  * comprise the type namespace, name, nested types (if any) and
8407  * generic type arguments (if any).
8408  *
8409  * The resulting info has the names in internal form.
8410  *
8411  */
8412 void
8413 mono_identifier_unescape_info (MonoTypeNameParse *info)
8414 {
8415         if (!info)
8416                 return;
8417         mono_identifier_unescape_type_name_chars(info->name_space);
8418         mono_identifier_unescape_type_name_chars(info->name);
8419         // but don't escape info->assembly
8420         if (info->type_arguments)
8421                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8422         if (info->nested)
8423                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8424 }
8425
8426 int
8427 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8428 {
8429         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8430         if (ok) {
8431                 mono_identifier_unescape_info (info);
8432         }
8433         return ok;
8434 }
8435
8436 static MonoType*
8437 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8438 {
8439         gboolean type_resolve = FALSE;
8440         MonoType *type;
8441         MonoImage *rootimage = image;
8442
8443         mono_error_init (error);
8444
8445         if (info->assembly.name) {
8446                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8447                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8448                         /* 
8449                          * This could happen in the AOT compiler case when the search hook is not
8450                          * installed.
8451                          */
8452                         assembly = image->assembly;
8453                 if (!assembly) {
8454                         /* then we must load the assembly ourselve - see #60439 */
8455                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8456                         if (!assembly)
8457                                 return NULL;
8458                 }
8459                 image = assembly->image;
8460         } else if (!image) {
8461                 image = mono_defaults.corlib;
8462         }
8463
8464         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8465         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8466                 mono_error_cleanup (error);
8467                 image = mono_defaults.corlib;
8468                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8469         }
8470
8471         return type;
8472 }
8473
8474 /**
8475  * mono_reflection_get_type_internal:
8476  *
8477  * Returns: may return NULL on success, sets error on failure.
8478  */
8479 static MonoType*
8480 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8481 {
8482         MonoClass *klass;
8483         GList *mod;
8484         int modval;
8485         gboolean bounded = FALSE;
8486         
8487         mono_error_init (error);
8488         if (!image)
8489                 image = mono_defaults.corlib;
8490
8491         if (!rootimage)
8492                 rootimage = mono_defaults.corlib;
8493
8494         if (ignorecase)
8495                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8496         else
8497                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8498
8499         if (!klass)
8500                 return NULL;
8501
8502         for (mod = info->nested; mod; mod = mod->next) {
8503                 gpointer iter = NULL;
8504                 MonoClass *parent;
8505
8506                 parent = klass;
8507                 mono_class_init (parent);
8508
8509                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8510                         char *lastp;
8511                         char *nested_name, *nested_nspace;
8512                         gboolean match = TRUE;
8513
8514                         lastp = strrchr ((const char *)mod->data, '.');
8515                         if (lastp) {
8516                                 /* Nested classes can have namespaces */
8517                                 int nspace_len;
8518
8519                                 nested_name = g_strdup (lastp + 1);
8520                                 nspace_len = lastp - (char*)mod->data;
8521                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8522                                 memcpy (nested_nspace, mod->data, nspace_len);
8523                                 nested_nspace [nspace_len] = '\0';
8524
8525                         } else {
8526                                 nested_name = (char *)mod->data;
8527                                 nested_nspace = NULL;
8528                         }
8529
8530                         if (nested_nspace) {
8531                                 if (ignorecase) {
8532                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8533                                                 match = FALSE;
8534                                 } else {
8535                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8536                                                 match = FALSE;
8537                                 }
8538                         }
8539                         if (match) {
8540                                 if (ignorecase) {
8541                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8542                                                 match = FALSE;
8543                                 } else {
8544                                         if (strcmp (klass->name, nested_name) != 0)
8545                                                 match = FALSE;
8546                                 }
8547                         }
8548                         if (lastp) {
8549                                 g_free (nested_name);
8550                                 g_free (nested_nspace);
8551                         }
8552                         if (match)
8553                                 break;
8554                 }
8555
8556                 if (!klass)
8557                         break;
8558         }
8559         if (!klass)
8560                 return NULL;
8561
8562         if (info->type_arguments) {
8563                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8564                 MonoReflectionType *the_type;
8565                 MonoType *instance;
8566                 int i;
8567
8568                 for (i = 0; i < info->type_arguments->len; i++) {
8569                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8570
8571                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8572                         if (!type_args [i]) {
8573                                 g_free (type_args);
8574                                 return NULL;
8575                         }
8576                 }
8577
8578                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8579                 if (!the_type)
8580                         return NULL;
8581
8582                 instance = mono_reflection_bind_generic_parameters (
8583                         the_type, info->type_arguments->len, type_args, error);
8584
8585                 g_free (type_args);
8586                 if (!instance)
8587                         return NULL;
8588
8589                 klass = mono_class_from_mono_type (instance);
8590         }
8591
8592         for (mod = info->modifiers; mod; mod = mod->next) {
8593                 modval = GPOINTER_TO_UINT (mod->data);
8594                 if (!modval) { /* byref: must be last modifier */
8595                         return &klass->this_arg;
8596                 } else if (modval == -1) {
8597                         klass = mono_ptr_class_get (&klass->byval_arg);
8598                 } else if (modval == -2) {
8599                         bounded = TRUE;
8600                 } else { /* array rank */
8601                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8602                 }
8603         }
8604
8605         return &klass->byval_arg;
8606 }
8607
8608 /*
8609  * mono_reflection_get_type:
8610  * @image: a metadata context
8611  * @info: type description structure
8612  * @ignorecase: flag for case-insensitive string compares
8613  * @type_resolve: whenever type resolve was already tried
8614  *
8615  * Build a MonoType from the type description in @info.
8616  * 
8617  */
8618
8619 MonoType*
8620 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8621         MonoError error;
8622         MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8623         mono_error_cleanup (&error);
8624         return result;
8625 }
8626
8627 /**
8628  * mono_reflection_get_type_checked:
8629  * @image: a metadata context
8630  * @info: type description structure
8631  * @ignorecase: flag for case-insensitive string compares
8632  * @type_resolve: whenever type resolve was already tried
8633  * @error: set on error.
8634  *
8635  * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8636  *
8637  */
8638 MonoType*
8639 mono_reflection_get_type_checked (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8640         mono_error_init (error);
8641         return mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, error);
8642 }
8643
8644
8645 static MonoType*
8646 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8647 {
8648         MonoReflectionAssemblyBuilder *abuilder;
8649         MonoType *type;
8650         int i;
8651
8652         mono_error_init (error);
8653         g_assert (assembly_is_dynamic (assembly));
8654         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8655         if (!abuilder)
8656                 return NULL;
8657
8658         /* Enumerate all modules */
8659
8660         type = NULL;
8661         if (abuilder->modules) {
8662                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8663                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8664                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8665                         if (type)
8666                                 break;
8667                         if (!mono_error_ok (error))
8668                                 return NULL;
8669                 }
8670         }
8671
8672         if (!type && abuilder->loaded_modules) {
8673                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8674                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8675                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8676                         if (type)
8677                                 break;
8678                         if (!mono_error_ok (error))
8679                                 return NULL;
8680                 }
8681         }
8682
8683         return type;
8684 }
8685         
8686 MonoType*
8687 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8688 {
8689         MonoType *type;
8690         MonoReflectionAssembly *assembly;
8691         GString *fullName;
8692         GList *mod;
8693
8694         mono_error_init (error);
8695
8696         if (image && image_is_dynamic (image))
8697                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8698         else {
8699                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8700         }
8701         return_val_if_nok (error, NULL);
8702
8703         if (type)
8704                 return type;
8705         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8706                 return NULL;
8707
8708         if (type_resolve) {
8709                 if (*type_resolve) 
8710                         return NULL;
8711                 else
8712                         *type_resolve = TRUE;
8713         }
8714         
8715         /* Reconstruct the type name */
8716         fullName = g_string_new ("");
8717         if (info->name_space && (info->name_space [0] != '\0'))
8718                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8719         else
8720                 g_string_printf (fullName, "%s", info->name);
8721         for (mod = info->nested; mod; mod = mod->next)
8722                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8723
8724         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8725         if (!is_ok (error)) {
8726                 g_string_free (fullName, TRUE);
8727                 return NULL;
8728         }
8729
8730         if (assembly) {
8731                 if (assembly_is_dynamic (assembly->assembly))
8732                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8733                                                                           info, ignorecase, error);
8734                 else
8735                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8736                                                                   info, ignorecase, error);
8737         }
8738         g_string_free (fullName, TRUE);
8739         return_val_if_nok (error, NULL);
8740         return type;
8741 }
8742
8743 void
8744 mono_reflection_free_type_info (MonoTypeNameParse *info)
8745 {
8746         g_list_free (info->modifiers);
8747         g_list_free (info->nested);
8748
8749         if (info->type_arguments) {
8750                 int i;
8751
8752                 for (i = 0; i < info->type_arguments->len; i++) {
8753                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8754
8755                         mono_reflection_free_type_info (subinfo);
8756                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8757                         g_free (subinfo);
8758                 }
8759
8760                 g_ptr_array_free (info->type_arguments, TRUE);
8761         }
8762 }
8763
8764 /*
8765  * mono_reflection_type_from_name:
8766  * @name: type name.
8767  * @image: a metadata context (can be NULL).
8768  *
8769  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8770  * it defaults to get the type from @image or, if @image is NULL or loading
8771  * from it fails, uses corlib.
8772  * 
8773  */
8774 MonoType*
8775 mono_reflection_type_from_name (char *name, MonoImage *image)
8776 {
8777         MonoError error;
8778         MonoType  *result = mono_reflection_type_from_name_checked (name, image, &error);
8779         mono_error_cleanup (&error);
8780         return result;
8781 }
8782
8783 /**
8784  * mono_reflection_type_from_name_checked:
8785  * @name: type name.
8786  * @image: a metadata context (can be NULL).
8787  * @error: set on errror.
8788  *
8789  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8790  * it defaults to get the type from @image or, if @image is NULL or loading
8791  * from it fails, uses corlib.  On failure returns NULL and sets @error.
8792  * 
8793  */
8794 MonoType*
8795 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8796 {
8797         MonoType *type = NULL;
8798         MonoTypeNameParse info;
8799         char *tmp;
8800
8801         mono_error_init (error);
8802         /* Make a copy since parse_type modifies its argument */
8803         tmp = g_strdup (name);
8804         
8805         /*g_print ("requested type %s\n", str);*/
8806         if (mono_reflection_parse_type (tmp, &info)) {
8807                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8808                 if (!is_ok (error)) {
8809                         g_free (tmp);
8810                         mono_reflection_free_type_info (&info);
8811                         return NULL;
8812                 }
8813         }
8814
8815         g_free (tmp);
8816         mono_reflection_free_type_info (&info);
8817         return type;
8818 }
8819
8820 /*
8821  * mono_reflection_get_token:
8822  *
8823  *   Return the metadata token of OBJ which should be an object
8824  * representing a metadata element.
8825  */
8826 guint32
8827 mono_reflection_get_token (MonoObject *obj)
8828 {
8829         MonoError error;
8830         guint32 result = mono_reflection_get_token_checked (obj, &error);
8831         mono_error_assert_ok (&error);
8832         return result;
8833 }
8834
8835 /**
8836  * mono_reflection_get_token_checked:
8837  * @obj: the object
8838  * @error: set on error
8839  *
8840  *   Return the metadata token of @obj which should be an object
8841  * representing a metadata element.  On failure sets @error.
8842  */
8843 guint32
8844 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8845 {
8846         MonoClass *klass;
8847         guint32 token = 0;
8848
8849         mono_error_init (error);
8850
8851         klass = obj->vtable->klass;
8852
8853         if (strcmp (klass->name, "MethodBuilder") == 0) {
8854                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8855
8856                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8857         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8858                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8859
8860                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8861         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8862                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8863
8864                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8865         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8866                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8867                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8868         } else if (strcmp (klass->name, "MonoType") == 0) {
8869                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8870                 return_val_if_nok (error, 0);
8871                 MonoClass *mc = mono_class_from_mono_type (type);
8872                 if (!mono_class_init (mc)) {
8873                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8874                         return 0;
8875                 }
8876
8877                 token = mc->type_token;
8878         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8879                    strcmp (klass->name, "MonoMethod") == 0 ||
8880                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8881                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8882                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8883                 if (m->method->is_inflated) {
8884                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8885                         return inflated->declaring->token;
8886                 } else {
8887                         token = m->method->token;
8888                 }
8889         } else if (strcmp (klass->name, "MonoField") == 0) {
8890                 MonoReflectionField *f = (MonoReflectionField*)obj;
8891
8892                 if (is_field_on_inst (f->field)) {
8893                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8894
8895                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8896                                 int field_index = f->field - dgclass->fields;
8897                                 MonoObject *obj;
8898
8899                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8900                                 obj = dgclass->field_objects [field_index];
8901                                 return mono_reflection_get_token_checked (obj, error);
8902                         }
8903                 }
8904                 token = mono_class_get_field_token (f->field);
8905         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8906                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8907
8908                 token = mono_class_get_property_token (p->property);
8909         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8910                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8911
8912                 token = mono_class_get_event_token (p->event);
8913         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8914                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8915                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8916                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8917
8918                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8919         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8920                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8921
8922                 token = m->token;
8923         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8924                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8925         } else {
8926                 mono_error_set_generic_error (error, "System", "NotImplementedException",
8927                                               "MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8928                 return 0;
8929         }
8930
8931         return token;
8932 }
8933
8934 static MonoClass*
8935 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8936 {
8937         char *n;
8938         MonoType *t;
8939         int slen = mono_metadata_decode_value (p, &p);
8940
8941         mono_error_init (error);
8942
8943         n = (char *)g_memdup (p, slen + 1);
8944         n [slen] = 0;
8945         t = mono_reflection_type_from_name_checked (n, image, error);
8946         if (!t) {
8947                 char *msg = g_strdup (mono_error_get_message (error));
8948                 mono_error_cleanup (error);
8949                 /* We don't free n, it's consumed by mono_error */
8950                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8951                 g_free (msg);
8952                 return NULL;
8953         }
8954         g_free (n);
8955         p += slen;
8956         *end = p;
8957         return mono_class_from_mono_type (t);
8958 }
8959
8960 static void*
8961 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8962 {
8963         int slen, type = t->type;
8964         MonoClass *tklass = t->data.klass;
8965
8966         mono_error_init (error);
8967
8968 handle_enum:
8969         switch (type) {
8970         case MONO_TYPE_U1:
8971         case MONO_TYPE_I1:
8972         case MONO_TYPE_BOOLEAN: {
8973                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8974                 *bval = *p;
8975                 *end = p + 1;
8976                 return bval;
8977         }
8978         case MONO_TYPE_CHAR:
8979         case MONO_TYPE_U2:
8980         case MONO_TYPE_I2: {
8981                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8982                 *val = read16 (p);
8983                 *end = p + 2;
8984                 return val;
8985         }
8986 #if SIZEOF_VOID_P == 4
8987         case MONO_TYPE_U:
8988         case MONO_TYPE_I:
8989 #endif
8990         case MONO_TYPE_R4:
8991         case MONO_TYPE_U4:
8992         case MONO_TYPE_I4: {
8993                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8994                 *val = read32 (p);
8995                 *end = p + 4;
8996                 return val;
8997         }
8998 #if SIZEOF_VOID_P == 8
8999         case MONO_TYPE_U: /* error out instead? this should probably not happen */
9000         case MONO_TYPE_I:
9001 #endif
9002         case MONO_TYPE_U8:
9003         case MONO_TYPE_I8: {
9004                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9005                 *val = read64 (p);
9006                 *end = p + 8;
9007                 return val;
9008         }
9009         case MONO_TYPE_R8: {
9010                 double *val = (double *)g_malloc (sizeof (double));
9011                 readr8 (p, val);
9012                 *end = p + 8;
9013                 return val;
9014         }
9015         case MONO_TYPE_VALUETYPE:
9016                 if (t->data.klass->enumtype) {
9017                         type = mono_class_enum_basetype (t->data.klass)->type;
9018                         goto handle_enum;
9019                 } else {
9020                         MonoClass *k =  t->data.klass;
9021                         
9022                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9023                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9024                                 *val = read64 (p);
9025                                 *end = p + 8;
9026                                 return val;
9027                         }
9028                 }
9029                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9030                 break;
9031                 
9032         case MONO_TYPE_STRING:
9033                 if (*p == (char)0xFF) {
9034                         *end = p + 1;
9035                         return NULL;
9036                 }
9037                 slen = mono_metadata_decode_value (p, &p);
9038                 *end = p + slen;
9039                 return mono_string_new_len (mono_domain_get (), p, slen);
9040         case MONO_TYPE_CLASS: {
9041                 MonoReflectionType *rt;
9042                 char *n;
9043                 MonoType *t;
9044                 if (*p == (char)0xFF) {
9045                         *end = p + 1;
9046                         return NULL;
9047                 }
9048 handle_type:
9049                 slen = mono_metadata_decode_value (p, &p);
9050                 n = (char *)g_memdup (p, slen + 1);
9051                 n [slen] = 0;
9052                 t = mono_reflection_type_from_name_checked (n, image, error);
9053                 if (!t) {
9054                         char *msg = g_strdup (mono_error_get_message (error));
9055                         mono_error_cleanup (error);
9056                         /* We don't free n, it's consumed by mono_error */
9057                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
9058                         g_free (msg);
9059                         return NULL;
9060                 }
9061                 g_free (n);
9062                 *end = p + slen;
9063
9064                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9065                 if (!mono_error_ok (error))
9066                         return NULL;
9067
9068                 return rt;
9069         }
9070         case MONO_TYPE_OBJECT: {
9071                 char subt = *p++;
9072                 MonoObject *obj;
9073                 MonoClass *subc = NULL;
9074                 void *val;
9075
9076                 if (subt == 0x50) {
9077                         goto handle_type;
9078                 } else if (subt == 0x0E) {
9079                         type = MONO_TYPE_STRING;
9080                         goto handle_enum;
9081                 } else if (subt == 0x1D) {
9082                         MonoType simple_type = {{0}};
9083                         int etype = *p;
9084                         p ++;
9085
9086                         type = MONO_TYPE_SZARRAY;
9087                         if (etype == 0x50) {
9088                                 tklass = mono_defaults.systemtype_class;
9089                         } else if (etype == 0x55) {
9090                                 tklass = load_cattr_enum_type (image, p, &p, error);
9091                                 if (!mono_error_ok (error))
9092                                         return NULL;
9093                         } else {
9094                                 if (etype == 0x51)
9095                                         /* See Partition II, Appendix B3 */
9096                                         etype = MONO_TYPE_OBJECT;
9097                                 simple_type.type = (MonoTypeEnum)etype;
9098                                 tklass = mono_class_from_mono_type (&simple_type);
9099                         }
9100                         goto handle_enum;
9101                 } else if (subt == 0x55) {
9102                         char *n;
9103                         MonoType *t;
9104                         slen = mono_metadata_decode_value (p, &p);
9105                         n = (char *)g_memdup (p, slen + 1);
9106                         n [slen] = 0;
9107                         t = mono_reflection_type_from_name_checked (n, image, error);
9108                         if (!t) {
9109                                 char *msg = g_strdup (mono_error_get_message (error));
9110                                 mono_error_cleanup (error);
9111                                 /* We don't free n, it's consumed by mono_error */
9112                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
9113                                 g_free (msg);
9114                                 return NULL;
9115                         }
9116                         g_free (n);
9117                         p += slen;
9118                         subc = mono_class_from_mono_type (t);
9119                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9120                         MonoType simple_type = {{0}};
9121                         simple_type.type = (MonoTypeEnum)subt;
9122                         subc = mono_class_from_mono_type (&simple_type);
9123                 } else {
9124                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9125                 }
9126                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9127                 obj = NULL;
9128                 if (mono_error_ok (error)) {
9129                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
9130                         g_assert (!subc->has_references);
9131                         if (mono_error_ok (error))
9132                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9133                 }
9134
9135                 g_free (val);
9136                 return obj;
9137         }
9138         case MONO_TYPE_SZARRAY: {
9139                 MonoArray *arr;
9140                 guint32 i, alen, basetype;
9141                 alen = read32 (p);
9142                 p += 4;
9143                 if (alen == 0xffffffff) {
9144                         *end = p;
9145                         return NULL;
9146                 }
9147                 arr = mono_array_new (mono_domain_get(), tklass, alen);
9148                 basetype = tklass->byval_arg.type;
9149                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9150                         basetype = mono_class_enum_basetype (tklass)->type;
9151                 switch (basetype)
9152                 {
9153                         case MONO_TYPE_U1:
9154                         case MONO_TYPE_I1:
9155                         case MONO_TYPE_BOOLEAN:
9156                                 for (i = 0; i < alen; i++) {
9157                                         MonoBoolean val = *p++;
9158                                         mono_array_set (arr, MonoBoolean, i, val);
9159                                 }
9160                                 break;
9161                         case MONO_TYPE_CHAR:
9162                         case MONO_TYPE_U2:
9163                         case MONO_TYPE_I2:
9164                                 for (i = 0; i < alen; i++) {
9165                                         guint16 val = read16 (p);
9166                                         mono_array_set (arr, guint16, i, val);
9167                                         p += 2;
9168                                 }
9169                                 break;
9170                         case MONO_TYPE_R4:
9171                         case MONO_TYPE_U4:
9172                         case MONO_TYPE_I4:
9173                                 for (i = 0; i < alen; i++) {
9174                                         guint32 val = read32 (p);
9175                                         mono_array_set (arr, guint32, i, val);
9176                                         p += 4;
9177                                 }
9178                                 break;
9179                         case MONO_TYPE_R8:
9180                                 for (i = 0; i < alen; i++) {
9181                                         double val;
9182                                         readr8 (p, &val);
9183                                         mono_array_set (arr, double, i, val);
9184                                         p += 8;
9185                                 }
9186                                 break;
9187                         case MONO_TYPE_U8:
9188                         case MONO_TYPE_I8:
9189                                 for (i = 0; i < alen; i++) {
9190                                         guint64 val = read64 (p);
9191                                         mono_array_set (arr, guint64, i, val);
9192                                         p += 8;
9193                                 }
9194                                 break;
9195                         case MONO_TYPE_CLASS:
9196                         case MONO_TYPE_OBJECT:
9197                         case MONO_TYPE_STRING:
9198                         case MONO_TYPE_SZARRAY:
9199                                 for (i = 0; i < alen; i++) {
9200                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9201                                         if (!mono_error_ok (error))
9202                                                 return NULL;
9203                                         mono_array_setref (arr, i, item);
9204                                 }
9205                                 break;
9206                         default:
9207                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9208                 }
9209                 *end=p;
9210                 return arr;
9211         }
9212         default:
9213                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9214         }
9215         return NULL;
9216 }
9217
9218 static MonoObject*
9219 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9220 {
9221         static MonoMethod *ctor;
9222         MonoObject *retval;
9223         void *params [2], *unboxed;
9224
9225         mono_error_init (error);
9226
9227         if (!ctor)
9228                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9229         
9230         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9231         return_val_if_nok (error, NULL);
9232
9233         params [1] = val;
9234         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9235         return_val_if_nok (error, NULL);
9236         unboxed = mono_object_unbox (retval);
9237
9238         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9239         return_val_if_nok (error, NULL);
9240
9241         return retval;
9242 }
9243
9244 static MonoObject*
9245 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9246 {
9247         static MonoMethod *ctor;
9248         MonoObject *retval;
9249         void *unboxed, *params [2];
9250
9251         mono_error_init (error);
9252
9253         if (!ctor)
9254                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9255
9256         params [0] = minfo;
9257         params [1] = typedarg;
9258         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9259         return_val_if_nok (error, NULL);
9260
9261         unboxed = mono_object_unbox (retval);
9262
9263         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9264         return_val_if_nok (error, NULL);
9265
9266         return retval;
9267 }
9268
9269 static gboolean
9270 type_is_reference (MonoType *type)
9271 {
9272         switch (type->type) {
9273         case MONO_TYPE_BOOLEAN:
9274         case MONO_TYPE_CHAR:
9275         case MONO_TYPE_U:
9276         case MONO_TYPE_I:
9277         case MONO_TYPE_U1:
9278         case MONO_TYPE_I1:
9279         case MONO_TYPE_U2:
9280         case MONO_TYPE_I2:
9281         case MONO_TYPE_U4:
9282         case MONO_TYPE_I4:
9283         case MONO_TYPE_U8:
9284         case MONO_TYPE_I8:
9285         case MONO_TYPE_R8:
9286         case MONO_TYPE_R4:
9287         case MONO_TYPE_VALUETYPE:
9288                 return FALSE;
9289         default:
9290                 return TRUE;
9291         }
9292 }
9293
9294 static void
9295 free_param_data (MonoMethodSignature *sig, void **params) {
9296         int i;
9297         for (i = 0; i < sig->param_count; ++i) {
9298                 if (!type_is_reference (sig->params [i]))
9299                         g_free (params [i]);
9300         }
9301 }
9302
9303 /*
9304  * Find the field index in the metadata FieldDef table.
9305  */
9306 static guint32
9307 find_field_index (MonoClass *klass, MonoClassField *field) {
9308         int i;
9309
9310         for (i = 0; i < klass->field.count; ++i) {
9311                 if (field == &klass->fields [i])
9312                         return klass->field.first + 1 + i;
9313         }
9314         return 0;
9315 }
9316
9317 /*
9318  * Find the property index in the metadata Property table.
9319  */
9320 static guint32
9321 find_property_index (MonoClass *klass, MonoProperty *property) {
9322         int i;
9323
9324         for (i = 0; i < klass->ext->property.count; ++i) {
9325                 if (property == &klass->ext->properties [i])
9326                         return klass->ext->property.first + 1 + i;
9327         }
9328         return 0;
9329 }
9330
9331 /*
9332  * Find the event index in the metadata Event table.
9333  */
9334 static guint32
9335 find_event_index (MonoClass *klass, MonoEvent *event) {
9336         int i;
9337
9338         for (i = 0; i < klass->ext->event.count; ++i) {
9339                 if (event == &klass->ext->events [i])
9340                         return klass->ext->event.first + 1 + i;
9341         }
9342         return 0;
9343 }
9344
9345 static MonoObject*
9346 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9347 {
9348         const char *p = (const char*)data;
9349         const char *named;
9350         guint32 i, j, num_named;
9351         MonoObject *attr;
9352         void *params_buf [32];
9353         void **params = NULL;
9354         MonoMethodSignature *sig;
9355         MonoObject *exc = NULL;
9356
9357         mono_error_init (error);
9358
9359         mono_class_init (method->klass);
9360
9361         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9362                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9363                 return NULL;
9364         }
9365
9366         if (len == 0) {
9367                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9368                 if (!mono_error_ok (error)) return NULL;
9369
9370                 mono_runtime_invoke_checked (method, attr, NULL, error);
9371                 if (!mono_error_ok (error))
9372                         return NULL;
9373
9374                 return attr;
9375         }
9376
9377         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9378                 return NULL;
9379
9380         /*g_print ("got attr %s\n", method->klass->name);*/
9381
9382         sig = mono_method_signature (method);
9383         if (sig->param_count < 32) {
9384                 params = params_buf;
9385                 memset (params, 0, sizeof (void*) * sig->param_count);
9386         } else {
9387                 /* Allocate using GC so it gets GC tracking */
9388                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9389         }
9390
9391         /* skip prolog */
9392         p += 2;
9393         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9394                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9395                 if (!mono_error_ok (error))
9396                         goto fail;
9397         }
9398
9399         named = p;
9400         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9401         if (!mono_error_ok (error)) goto fail;
9402
9403         mono_runtime_try_invoke (method, attr, params, &exc, error);
9404         if (!mono_error_ok (error))
9405                 goto fail;
9406         if (exc)
9407                 goto fail;
9408
9409         num_named = read16 (named);
9410         named += 2;
9411         for (j = 0; j < num_named; j++) {
9412                 gint name_len;
9413                 char *name, named_type, data_type;
9414                 named_type = *named++;
9415                 data_type = *named++; /* type of data */
9416                 if (data_type == MONO_TYPE_SZARRAY)
9417                         data_type = *named++;
9418                 if (data_type == MONO_TYPE_ENUM) {
9419                         gint type_len;
9420                         char *type_name;
9421                         type_len = mono_metadata_decode_blob_size (named, &named);
9422                         type_name = (char *)g_malloc (type_len + 1);
9423                         memcpy (type_name, named, type_len);
9424                         type_name [type_len] = 0;
9425                         named += type_len;
9426                         /* FIXME: lookup the type and check type consistency */
9427                         g_free (type_name);
9428                 }
9429                 name_len = mono_metadata_decode_blob_size (named, &named);
9430                 name = (char *)g_malloc (name_len + 1);
9431                 memcpy (name, named, name_len);
9432                 name [name_len] = 0;
9433                 named += name_len;
9434                 if (named_type == 0x53) {
9435                         MonoClassField *field;
9436                         void *val;
9437
9438                         /* how this fail is a blackbox */
9439                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9440                         if (!field) {
9441                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9442                                 g_free (name);
9443                                 goto fail;
9444                         }
9445
9446                         val = load_cattr_value (image, field->type, named, &named, error);
9447                         if (!mono_error_ok (error)) {
9448                                 g_free (name);
9449                                 if (!type_is_reference (field->type))
9450                                         g_free (val);
9451                                 goto fail;
9452                         }
9453
9454                         mono_field_set_value (attr, field, val);
9455                         if (!type_is_reference (field->type))
9456                                 g_free (val);
9457                 } else if (named_type == 0x54) {
9458                         MonoProperty *prop;
9459                         void *pparams [1];
9460                         MonoType *prop_type;
9461
9462                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9463
9464                         if (!prop) {
9465                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9466                                 g_free (name);
9467                                 goto fail;
9468                         }
9469
9470                         if (!prop->set) {
9471                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9472                                 g_free (name);
9473                                 goto fail;
9474                         }
9475
9476                         /* can we have more that 1 arg in a custom attr named property? */
9477                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9478                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9479
9480                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9481                         if (!mono_error_ok (error)) {
9482                                 g_free (name);
9483                                 if (!type_is_reference (prop_type))
9484                                         g_free (pparams [0]);
9485                                 goto fail;
9486                         }
9487
9488
9489                         mono_property_set_value (prop, attr, pparams, NULL);
9490                         if (!type_is_reference (prop_type))
9491                                 g_free (pparams [0]);
9492                 }
9493                 g_free (name);
9494         }
9495
9496         free_param_data (method->signature, params);
9497         if (params != params_buf)
9498                 mono_gc_free_fixed (params);
9499
9500         return attr;
9501
9502 fail:
9503         free_param_data (method->signature, params);
9504         if (params != params_buf)
9505                 mono_gc_free_fixed (params);
9506         if (exc)
9507                 mono_raise_exception ((MonoException*)exc);
9508         return NULL;
9509 }
9510         
9511 /*
9512  * mono_reflection_create_custom_attr_data_args:
9513  *
9514  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9515  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9516  * NAMED_ARG_INFO will contain information about the named arguments.
9517  */
9518 void
9519 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)
9520 {
9521         MonoArray *typedargs, *namedargs;
9522         MonoClass *attrklass;
9523         MonoDomain *domain;
9524         const char *p = (const char*)data;
9525         const char *named;
9526         guint32 i, j, num_named;
9527         CattrNamedArg *arginfo = NULL;
9528
9529         *typed_args = NULL;
9530         *named_args = NULL;
9531         *named_arg_info = NULL;
9532
9533         mono_error_init (error);
9534
9535         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9536                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9537                 return;
9538         }
9539
9540         mono_class_init (method->klass);
9541         
9542         domain = mono_domain_get ();
9543
9544         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9545                 return;
9546
9547         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9548         
9549         /* skip prolog */
9550         p += 2;
9551         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9552                 MonoObject *obj;
9553                 void *val;
9554
9555                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9556                 if (!mono_error_ok (error)) {
9557                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9558                                 g_free (val);
9559                         return;
9560                 }
9561
9562                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9563                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9564                 mono_array_setref (typedargs, i, obj);
9565
9566                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9567                         g_free (val);
9568         }
9569
9570         named = p;
9571         num_named = read16 (named);
9572         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9573         named += 2;
9574         attrklass = method->klass;
9575
9576         arginfo = g_new0 (CattrNamedArg, num_named);
9577         *named_arg_info = arginfo;
9578
9579         for (j = 0; j < num_named; j++) {
9580                 gint name_len;
9581                 char *name, named_type, data_type;
9582                 named_type = *named++;
9583                 data_type = *named++; /* type of data */
9584                 if (data_type == MONO_TYPE_SZARRAY)
9585                         data_type = *named++;
9586                 if (data_type == MONO_TYPE_ENUM) {
9587                         gint type_len;
9588                         char *type_name;
9589                         type_len = mono_metadata_decode_blob_size (named, &named);
9590                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9591                                 goto fail;
9592
9593                         type_name = (char *)g_malloc (type_len + 1);
9594                         memcpy (type_name, named, type_len);
9595                         type_name [type_len] = 0;
9596                         named += type_len;
9597                         /* FIXME: lookup the type and check type consistency */
9598                         g_free (type_name);
9599                 }
9600                 name_len = mono_metadata_decode_blob_size (named, &named);
9601                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9602                         goto fail;
9603                 name = (char *)g_malloc (name_len + 1);
9604                 memcpy (name, named, name_len);
9605                 name [name_len] = 0;
9606                 named += name_len;
9607                 if (named_type == 0x53) {
9608                         MonoObject *obj;
9609                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9610                         void *val;
9611
9612                         if (!field) {
9613                                 g_free (name);
9614                                 goto fail;
9615                         }
9616
9617                         arginfo [j].type = field->type;
9618                         arginfo [j].field = field;
9619
9620                         val = load_cattr_value (image, field->type, named, &named, error);
9621                         if (!mono_error_ok (error)) {
9622                                 if (!type_is_reference (field->type))
9623                                         g_free (val);
9624                                 g_free (name);
9625                                 return;
9626                         }
9627
9628                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9629                         mono_array_setref (namedargs, j, obj);
9630                         if (!type_is_reference (field->type))
9631                                 g_free (val);
9632                 } else if (named_type == 0x54) {
9633                         MonoObject *obj;
9634                         MonoType *prop_type;
9635                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9636                         void *val;
9637
9638                         if (!prop || !prop->set) {
9639                                 g_free (name);
9640                                 goto fail;
9641                         }
9642
9643                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9644                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9645
9646                         arginfo [j].type = prop_type;
9647                         arginfo [j].prop = prop;
9648
9649                         val = load_cattr_value (image, prop_type, named, &named, error);
9650                         if (!mono_error_ok (error)) {
9651                                 if (!type_is_reference (prop_type))
9652                                         g_free (val);
9653                                 g_free (name);
9654                                 return;
9655                         }
9656
9657                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9658                         mono_array_setref (namedargs, j, obj);
9659                         if (!type_is_reference (prop_type))
9660                                 g_free (val);
9661                 }
9662                 g_free (name);
9663         }
9664
9665         *typed_args = typedargs;
9666         *named_args = namedargs;
9667         return;
9668 fail:
9669         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9670         g_free (arginfo);
9671         *named_arg_info = NULL;
9672 }
9673
9674 void
9675 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9676 {
9677         MonoDomain *domain;
9678         MonoArray *typedargs, *namedargs;
9679         MonoImage *image;
9680         MonoMethod *method;
9681         CattrNamedArg *arginfo = NULL;
9682         MonoError error;
9683         int i;
9684
9685         mono_error_init (&error);
9686
9687         *ctor_args = NULL;
9688         *named_args = NULL;
9689
9690         if (len == 0)
9691                 return;
9692
9693         image = assembly->assembly->image;
9694         method = ref_method->method;
9695         domain = mono_object_domain (ref_method);
9696
9697         if (!mono_class_init (method->klass))
9698                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9699
9700         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9701         if (!mono_error_ok (&error))
9702                 goto leave;
9703
9704         if (mono_loader_get_last_error ()) {
9705                 mono_error_set_from_loader_error (&error);
9706                 goto leave;
9707         }
9708
9709         if (!typedargs || !namedargs)
9710                 goto leave;
9711
9712         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9713                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9714                 MonoObject *typedarg;
9715
9716                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9717                 if (!is_ok (&error))
9718                         goto leave;
9719                 mono_array_setref (typedargs, i, typedarg);
9720         }
9721
9722         for (i = 0; i < mono_array_length (namedargs); ++i) {
9723                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9724                 MonoObject *typedarg, *namedarg, *minfo;
9725
9726                 if (arginfo [i].prop) {
9727                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9728                         if (!minfo)
9729                                 goto leave;
9730                 } else {
9731                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9732                         if (!mono_error_ok (&error))
9733                                 goto leave;
9734                 }
9735
9736                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9737                 if (!is_ok (&error))
9738                         goto leave;
9739                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9740                 if (!is_ok (&error))
9741                         goto leave;
9742
9743                 mono_array_setref (namedargs, i, namedarg);
9744         }
9745
9746         *ctor_args = typedargs;
9747         *named_args = namedargs;
9748 leave:
9749         g_free (arginfo);
9750         mono_error_raise_exception (&error);
9751
9752 }
9753
9754 static MonoObject*
9755 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9756 {
9757         static MonoMethod *ctor;
9758
9759         MonoDomain *domain;
9760         MonoObject *attr;
9761         void *params [4];
9762
9763         mono_error_init (error);
9764
9765         g_assert (image->assembly);
9766
9767         if (!ctor)
9768                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9769
9770         domain = mono_domain_get ();
9771         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9772         return_val_if_nok (error, NULL);
9773         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9774         return_val_if_nok (error, NULL);
9775         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9776         return_val_if_nok (error, NULL);
9777         params [2] = (gpointer)&cattr->data;
9778         params [3] = &cattr->data_size;
9779
9780         mono_runtime_invoke_checked (ctor, attr, params, error);
9781         return_val_if_nok (error, NULL);
9782         return attr;
9783 }
9784
9785 static MonoArray*
9786 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9787 {
9788         MonoArray *result;
9789         MonoObject *attr;
9790         int i, n;
9791
9792         mono_error_init (error);
9793
9794         n = 0;
9795         for (i = 0; i < cinfo->num_attrs; ++i) {
9796                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9797                         n ++;
9798         }
9799
9800         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9801         n = 0;
9802         for (i = 0; i < cinfo->num_attrs; ++i) {
9803                 if (!cinfo->attrs [i].ctor) {
9804                         /* The cattr type is not finished yet */
9805                         /* We should include the type name but cinfo doesn't contain it */
9806                         mono_error_set_type_load_name (error, NULL, NULL, "");
9807                         return NULL;
9808                 }
9809                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9810                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9811                         if (!mono_error_ok (error))
9812                                 return result;
9813                         mono_array_setref (result, n, attr);
9814                         n ++;
9815                 }
9816         }
9817         return result;
9818 }
9819
9820 MonoArray*
9821 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9822 {
9823         MonoError error;
9824         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9825         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9826
9827         return result;
9828 }
9829
9830 static MonoArray*
9831 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9832 {
9833         MonoArray *result;
9834         MonoObject *attr;
9835         int i;
9836         
9837         mono_error_init (error);
9838         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9839         for (i = 0; i < cinfo->num_attrs; ++i) {
9840                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9841                 return_val_if_nok (error, NULL);
9842                 mono_array_setref (result, i, attr);
9843         }
9844         return result;
9845 }
9846
9847 /**
9848  * mono_custom_attrs_from_index:
9849  *
9850  * Returns: NULL if no attributes are found or if a loading error occurs.
9851  */
9852 MonoCustomAttrInfo*
9853 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9854 {
9855         MonoError error;
9856         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9857         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9858         return result;
9859 }
9860 /**
9861  * mono_custom_attrs_from_index_checked:
9862  *
9863  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9864  */
9865 MonoCustomAttrInfo*
9866 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9867 {
9868         guint32 mtoken, i, len;
9869         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9870         MonoTableInfo *ca;
9871         MonoCustomAttrInfo *ainfo;
9872         GList *tmp, *list = NULL;
9873         const char *data;
9874         MonoCustomAttrEntry* attr;
9875
9876         mono_error_init (error);
9877
9878         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9879
9880         i = mono_metadata_custom_attrs_from_index (image, idx);
9881         if (!i)
9882                 return NULL;
9883         i --;
9884         while (i < ca->rows) {
9885                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9886                         break;
9887                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9888                 ++i;
9889         }
9890         len = g_list_length (list);
9891         if (!len)
9892                 return NULL;
9893         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9894         ainfo->num_attrs = len;
9895         ainfo->image = image;
9896         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9897                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9898                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9899                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9900                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9901                         mtoken |= MONO_TOKEN_METHOD_DEF;
9902                         break;
9903                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9904                         mtoken |= MONO_TOKEN_MEMBER_REF;
9905                         break;
9906                 default:
9907                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9908                         break;
9909                 }
9910                 attr = &ainfo->attrs [i - 1];
9911                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9912                 if (!attr->ctor) {
9913                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9914                         g_list_free (list);
9915                         g_free (ainfo);
9916                         return NULL;
9917                 }
9918
9919                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9920                         /*FIXME raising an exception here doesn't make any sense*/
9921                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9922                         g_list_free (list);
9923                         g_free (ainfo);
9924                         return NULL;
9925                 }
9926                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9927                 attr->data_size = mono_metadata_decode_value (data, &data);
9928                 attr->data = (guchar*)data;
9929         }
9930         g_list_free (list);
9931
9932         return ainfo;
9933 }
9934
9935 MonoCustomAttrInfo*
9936 mono_custom_attrs_from_method (MonoMethod *method)
9937 {
9938         MonoError error;
9939         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9940         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9941         return result;
9942 }
9943
9944 MonoCustomAttrInfo*
9945 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9946 {
9947         guint32 idx;
9948
9949         mono_error_init (error);
9950
9951         /*
9952          * An instantiated method has the same cattrs as the generic method definition.
9953          *
9954          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9955          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9956          */
9957         if (method->is_inflated)
9958                 method = ((MonoMethodInflated *) method)->declaring;
9959         
9960         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9961                 return lookup_custom_attr (method->klass->image, method);
9962
9963         if (!method->token)
9964                 /* Synthetic methods */
9965                 return NULL;
9966
9967         idx = mono_method_get_index (method);
9968         idx <<= MONO_CUSTOM_ATTR_BITS;
9969         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9970         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9971 }
9972
9973 MonoCustomAttrInfo*
9974 mono_custom_attrs_from_class (MonoClass *klass)
9975 {
9976         MonoError error;
9977         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9978         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9979         return result;
9980 }
9981
9982 MonoCustomAttrInfo*
9983 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9984 {
9985         guint32 idx;
9986
9987         mono_error_init (error);
9988
9989         if (klass->generic_class)
9990                 klass = klass->generic_class->container_class;
9991
9992         if (image_is_dynamic (klass->image))
9993                 return lookup_custom_attr (klass->image, klass);
9994
9995         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9996                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9997                 idx <<= MONO_CUSTOM_ATTR_BITS;
9998                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9999         } else {
10000                 idx = mono_metadata_token_index (klass->type_token);
10001                 idx <<= MONO_CUSTOM_ATTR_BITS;
10002                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10003         }
10004         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10005 }
10006
10007 MonoCustomAttrInfo*
10008 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10009 {
10010         MonoError error;
10011         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10012         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10013         return result;
10014 }
10015
10016 MonoCustomAttrInfo*
10017 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10018 {
10019         guint32 idx;
10020         
10021         mono_error_init (error);
10022
10023         if (image_is_dynamic (assembly->image))
10024                 return lookup_custom_attr (assembly->image, assembly);
10025         idx = 1; /* there is only one assembly */
10026         idx <<= MONO_CUSTOM_ATTR_BITS;
10027         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10028         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10029 }
10030
10031 static MonoCustomAttrInfo*
10032 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10033 {
10034         guint32 idx;
10035         
10036         if (image_is_dynamic (image))
10037                 return lookup_custom_attr (image, image);
10038         idx = 1; /* there is only one module */
10039         idx <<= MONO_CUSTOM_ATTR_BITS;
10040         idx |= MONO_CUSTOM_ATTR_MODULE;
10041         return mono_custom_attrs_from_index_checked (image, idx, error);
10042 }
10043
10044 MonoCustomAttrInfo*
10045 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10046 {
10047         MonoError error;
10048         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10049         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10050         return result;
10051 }
10052
10053 MonoCustomAttrInfo*
10054 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10055 {
10056         guint32 idx;
10057         
10058         if (image_is_dynamic (klass->image)) {
10059                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10060                 return lookup_custom_attr (klass->image, property);
10061         }
10062         idx = find_property_index (klass, property);
10063         idx <<= MONO_CUSTOM_ATTR_BITS;
10064         idx |= MONO_CUSTOM_ATTR_PROPERTY;
10065         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10066 }
10067
10068 MonoCustomAttrInfo*
10069 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10070 {
10071         MonoError error;
10072         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10073         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10074         return result;
10075 }
10076
10077 MonoCustomAttrInfo*
10078 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10079 {
10080         guint32 idx;
10081         
10082         if (image_is_dynamic (klass->image)) {
10083                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10084                 return lookup_custom_attr (klass->image, event);
10085         }
10086         idx = find_event_index (klass, event);
10087         idx <<= MONO_CUSTOM_ATTR_BITS;
10088         idx |= MONO_CUSTOM_ATTR_EVENT;
10089         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10090 }
10091
10092 MonoCustomAttrInfo*
10093 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10094 {
10095         MonoError error;
10096         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10097         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10098         return result;
10099 }
10100
10101 MonoCustomAttrInfo*
10102 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10103 {
10104         guint32 idx;
10105         mono_error_init (error);
10106
10107         if (image_is_dynamic (klass->image)) {
10108                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10109                 return lookup_custom_attr (klass->image, field);
10110         }
10111         idx = find_field_index (klass, field);
10112         idx <<= MONO_CUSTOM_ATTR_BITS;
10113         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10114         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10115 }
10116
10117 /**
10118  * mono_custom_attrs_from_param:
10119  * @method: handle to the method that we want to retrieve custom parameter information from
10120  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10121  *
10122  * The result must be released with mono_custom_attrs_free().
10123  *
10124  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10125  */
10126 MonoCustomAttrInfo*
10127 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10128 {
10129         MonoError error;
10130         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10131         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10132         return result;
10133 }
10134
10135 /**
10136  * mono_custom_attrs_from_param_checked:
10137  * @method: handle to the method that we want to retrieve custom parameter information from
10138  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10139  * @error: set on error
10140  *
10141  * The result must be released with mono_custom_attrs_free().
10142  *
10143  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
10144  */
10145 MonoCustomAttrInfo*
10146 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10147 {
10148         MonoTableInfo *ca;
10149         guint32 i, idx, method_index;
10150         guint32 param_list, param_last, param_pos, found;
10151         MonoImage *image;
10152         MonoReflectionMethodAux *aux;
10153
10154         mono_error_init (error);
10155
10156         /*
10157          * An instantiated method has the same cattrs as the generic method definition.
10158          *
10159          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10160          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10161          */
10162         if (method->is_inflated)
10163                 method = ((MonoMethodInflated *) method)->declaring;
10164
10165         if (image_is_dynamic (method->klass->image)) {
10166                 MonoCustomAttrInfo *res, *ainfo;
10167                 int size;
10168
10169                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10170                 if (!aux || !aux->param_cattr)
10171                         return NULL;
10172
10173                 /* Need to copy since it will be freed later */
10174                 ainfo = aux->param_cattr [param];
10175                 if (!ainfo)
10176                         return NULL;
10177                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10178                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10179                 memcpy (res, ainfo, size);
10180                 return res;
10181         }
10182
10183         image = method->klass->image;
10184         method_index = mono_method_get_index (method);
10185         if (!method_index)
10186                 return NULL;
10187         ca = &image->tables [MONO_TABLE_METHOD];
10188
10189         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10190         if (method_index == ca->rows) {
10191                 ca = &image->tables [MONO_TABLE_PARAM];
10192                 param_last = ca->rows + 1;
10193         } else {
10194                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10195                 ca = &image->tables [MONO_TABLE_PARAM];
10196         }
10197         found = FALSE;
10198         for (i = param_list; i < param_last; ++i) {
10199                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10200                 if (param_pos == param) {
10201                         found = TRUE;
10202                         break;
10203                 }
10204         }
10205         if (!found)
10206                 return NULL;
10207         idx = i;
10208         idx <<= MONO_CUSTOM_ATTR_BITS;
10209         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10210         return mono_custom_attrs_from_index_checked (image, idx, error);
10211 }
10212
10213 gboolean
10214 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10215 {
10216         int i;
10217         MonoClass *klass;
10218         for (i = 0; i < ainfo->num_attrs; ++i) {
10219                 klass = ainfo->attrs [i].ctor->klass;
10220                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10221                         return TRUE;
10222         }
10223         return FALSE;
10224 }
10225
10226 MonoObject*
10227 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10228 {
10229         MonoError error;
10230         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10231         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10232         return res;
10233 }
10234
10235 MonoObject*
10236 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10237 {
10238         int i, attr_index;
10239         MonoClass *klass;
10240         MonoArray *attrs;
10241
10242         mono_error_init (error);
10243
10244         attr_index = -1;
10245         for (i = 0; i < ainfo->num_attrs; ++i) {
10246                 klass = ainfo->attrs [i].ctor->klass;
10247                 if (mono_class_has_parent (klass, attr_klass)) {
10248                         attr_index = i;
10249                         break;
10250                 }
10251         }
10252         if (attr_index == -1)
10253                 return NULL;
10254
10255         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10256         if (!mono_error_ok (error))
10257                 return NULL;
10258         return mono_array_get (attrs, MonoObject*, attr_index);
10259 }
10260
10261 /*
10262  * mono_reflection_get_custom_attrs_info:
10263  * @obj: a reflection object handle
10264  *
10265  * Return the custom attribute info for attributes defined for the
10266  * reflection handle @obj. The objects.
10267  *
10268  * FIXME this function leaks like a sieve for SRE objects.
10269  */
10270 MonoCustomAttrInfo*
10271 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10272 {
10273         MonoError error;
10274         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10275         mono_error_assert_ok (&error);
10276         return result;
10277 }
10278
10279 /**
10280  * mono_reflection_get_custom_attrs_info_checked:
10281  * @obj: a reflection object handle
10282  * @error: set on error
10283  *
10284  * Return the custom attribute info for attributes defined for the
10285  * reflection handle @obj. The objects.
10286  *
10287  * On failure returns NULL and sets @error.
10288  *
10289  * FIXME this function leaks like a sieve for SRE objects.
10290  */
10291 MonoCustomAttrInfo*
10292 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10293 {
10294         MonoClass *klass;
10295         MonoCustomAttrInfo *cinfo = NULL;
10296         
10297         mono_error_init (error);
10298
10299         klass = obj->vtable->klass;
10300         if (klass == mono_defaults.monotype_class) {
10301                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10302                 return_val_if_nok (error, NULL);
10303                 klass = mono_class_from_mono_type (type);
10304                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10305                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10306                 return_val_if_nok (error, NULL);
10307         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10308                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10309                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10310                 return_val_if_nok (error, NULL);
10311         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10312                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10313                 cinfo = mono_custom_attrs_from_module (module->image, error);
10314                 return_val_if_nok (error, NULL);
10315         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10316                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10317                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10318                 return_val_if_nok (error, NULL);
10319         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10320                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10321                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10322                 return_val_if_nok (error, NULL);
10323         } else if (strcmp ("MonoField", klass->name) == 0) {
10324                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10325                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10326                 return_val_if_nok (error, NULL);
10327         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10328                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10329                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10330                 return_val_if_nok (error, NULL);
10331         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10332                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10333                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10334                 return_val_if_nok (error, NULL);
10335         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10336                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10337                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10338                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10339                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10340                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10341                         return_val_if_nok (error, NULL);
10342                 } else if (is_sr_mono_property (member_class)) {
10343                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10344                         MonoMethod *method;
10345                         if (!(method = prop->property->get))
10346                                 method = prop->property->set;
10347                         g_assert (method);
10348
10349                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10350                         return_val_if_nok (error, NULL);
10351                 } 
10352 #ifndef DISABLE_REFLECTION_EMIT
10353                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10354                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10355                         return_val_if_nok (error, NULL);
10356                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10357                         return_val_if_nok (error, NULL);
10358                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10359                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10360                         MonoMethod *method = NULL;
10361                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10362                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10363                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10364                                 method = ((MonoReflectionMethod *)c->cb)->method;
10365                         else
10366                                 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));
10367
10368                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10369                         return_val_if_nok (error, NULL);
10370                 } 
10371 #endif
10372                 else {
10373                         char *type_name = mono_type_get_full_name (member_class);
10374                         mono_error_set_generic_error (error, "System", "NotSupportedException",
10375                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10376                                                       type_name);
10377                         g_free (type_name);
10378                         return NULL;
10379                 }
10380         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10381                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10382                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10383         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10384                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10385                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10386         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10387                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10388                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10389         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10390                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10391                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10392         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10393                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10394                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10395         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10396                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10397                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10398         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10399                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10400                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10401                 return_val_if_nok (error, NULL);
10402         } else { /* handle other types here... */
10403                 g_error ("get custom attrs not yet supported for %s", klass->name);
10404         }
10405
10406         return cinfo;
10407 }
10408
10409 /*
10410  * mono_reflection_get_custom_attrs_by_type:
10411  * @obj: a reflection object handle
10412  *
10413  * Return an array with all the custom attributes defined of the
10414  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10415  * of that type are returned. The objects are fully build. Return NULL if a loading error
10416  * occurs.
10417  */
10418 MonoArray*
10419 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10420 {
10421         MonoArray *result;
10422         MonoCustomAttrInfo *cinfo;
10423
10424         mono_error_init (error);
10425
10426         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10427         return_val_if_nok (error, NULL);
10428         if (cinfo) {
10429                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10430                 if (!result)
10431                         return NULL;
10432                 if (!cinfo->cached)
10433                         mono_custom_attrs_free (cinfo);
10434         } else {
10435                 mono_loader_assert_no_error ();
10436                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10437         }
10438
10439         return result;
10440 }
10441
10442 /*
10443  * mono_reflection_get_custom_attrs:
10444  * @obj: a reflection object handle
10445  *
10446  * Return an array with all the custom attributes defined of the
10447  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10448  * occurs.
10449  */
10450 MonoArray*
10451 mono_reflection_get_custom_attrs (MonoObject *obj)
10452 {
10453         MonoError error;
10454
10455         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10456 }
10457
10458 /*
10459  * mono_reflection_get_custom_attrs_data:
10460  * @obj: a reflection obj handle
10461  *
10462  * Returns an array of System.Reflection.CustomAttributeData,
10463  * which include information about attributes reflected on
10464  * types loaded using the Reflection Only methods
10465  */
10466 MonoArray*
10467 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10468 {
10469         MonoError error;
10470         MonoArray* result;
10471         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10472         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10473         return result;
10474 }
10475
10476 /*
10477  * mono_reflection_get_custom_attrs_data_checked:
10478  * @obj: a reflection obj handle
10479  * @error: set on error
10480  *
10481  * Returns an array of System.Reflection.CustomAttributeData,
10482  * which include information about attributes reflected on
10483  * types loaded using the Reflection Only methods
10484  */
10485 MonoArray*
10486 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10487 {
10488         MonoArray *result;
10489         MonoCustomAttrInfo *cinfo;
10490
10491         mono_error_init (error);
10492
10493         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10494         return_val_if_nok (error, NULL);
10495         if (cinfo) {
10496                 result = mono_custom_attrs_data_construct (cinfo, error);
10497                 return_val_if_nok (error, NULL);
10498                 if (!cinfo->cached)
10499                         mono_custom_attrs_free (cinfo);
10500         } else
10501                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10502
10503         if (mono_loader_get_last_error ())
10504                 mono_error_set_from_loader_error (error);
10505
10506         return result;
10507 }
10508
10509 static MonoReflectionType*
10510 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10511 {
10512         static MonoMethod *method_get_underlying_system_type = NULL;
10513         MonoReflectionType *rt;
10514         MonoMethod *usertype_method;
10515
10516         mono_error_init (error);
10517
10518         if (!method_get_underlying_system_type)
10519                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10520
10521         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10522
10523         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10524
10525         return rt;
10526 }
10527
10528
10529 static gboolean
10530 is_corlib_type (MonoClass *klass)
10531 {
10532         return klass->image == mono_defaults.corlib;
10533 }
10534
10535 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10536         static MonoClass *cached_class; \
10537         if (cached_class) \
10538                 return cached_class == _class; \
10539         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10540                 cached_class = _class; \
10541                 return TRUE; \
10542         } \
10543         return FALSE; \
10544 } while (0) \
10545
10546
10547 #ifndef DISABLE_REFLECTION_EMIT
10548 static gboolean
10549 is_sre_array (MonoClass *klass)
10550 {
10551         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10552 }
10553
10554 static gboolean
10555 is_sre_byref (MonoClass *klass)
10556 {
10557         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10558 }
10559
10560 static gboolean
10561 is_sre_pointer (MonoClass *klass)
10562 {
10563         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10564 }
10565
10566 static gboolean
10567 is_sre_generic_instance (MonoClass *klass)
10568 {
10569         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10570 }
10571
10572 static gboolean
10573 is_sre_type_builder (MonoClass *klass)
10574 {
10575         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10576 }
10577
10578 static gboolean
10579 is_sre_method_builder (MonoClass *klass)
10580 {
10581         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10582 }
10583
10584 static gboolean
10585 is_sre_ctor_builder (MonoClass *klass)
10586 {
10587         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10588 }
10589
10590 static gboolean
10591 is_sre_field_builder (MonoClass *klass)
10592 {
10593         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10594 }
10595
10596 static gboolean
10597 is_sre_method_on_tb_inst (MonoClass *klass)
10598 {
10599         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10600 }
10601
10602 static gboolean
10603 is_sre_ctor_on_tb_inst (MonoClass *klass)
10604 {
10605         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10606 }
10607
10608 MonoType*
10609 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10610 {
10611         MonoClass *klass;
10612         mono_error_init (error);
10613
10614         if (!ref)
10615                 return NULL;
10616         if (ref->type)
10617                 return ref->type;
10618
10619         if (is_usertype (ref)) {
10620                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10621                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10622                         return NULL;
10623                 if (ref->type)
10624                         return ref->type;
10625         }
10626
10627         klass = mono_object_class (ref);
10628
10629         if (is_sre_array (klass)) {
10630                 MonoType *res;
10631                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10632                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10633                 return_val_if_nok (error, NULL);
10634                 g_assert (base);
10635                 if (sre_array->rank == 0) //single dimentional array
10636                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10637                 else
10638                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10639                 sre_array->type.type = res;
10640                 return res;
10641         } else if (is_sre_byref (klass)) {
10642                 MonoType *res;
10643                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10644                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10645                 return_val_if_nok (error, NULL);
10646                 g_assert (base);
10647                 res = &mono_class_from_mono_type (base)->this_arg;
10648                 sre_byref->type.type = res;
10649                 return res;
10650         } else if (is_sre_pointer (klass)) {
10651                 MonoType *res;
10652                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10653                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10654                 return_val_if_nok (error, NULL);
10655                 g_assert (base);
10656                 res = &mono_ptr_class_get (base)->byval_arg;
10657                 sre_pointer->type.type = res;
10658                 return res;
10659         } else if (is_sre_generic_instance (klass)) {
10660                 MonoType *res, **types;
10661                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10662                 int i, count;
10663
10664                 count = mono_array_length (gclass->type_arguments);
10665                 types = g_new0 (MonoType*, count);
10666                 for (i = 0; i < count; ++i) {
10667                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10668                         types [i] = mono_reflection_type_get_handle (t, error);
10669                         if (!types[i] || !is_ok (error)) {
10670                                 g_free (types);
10671                                 return NULL;
10672                         }
10673                 }
10674
10675                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10676                 g_free (types);
10677                 g_assert (res);
10678                 gclass->type.type = res;
10679                 return res;
10680         }
10681
10682         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10683         return NULL;
10684 }
10685
10686 void
10687 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10688 {
10689         MonoError error;
10690         mono_reflection_type_get_handle (type, &error);
10691         mono_error_set_pending_exception (&error);
10692 }
10693
10694 static gboolean
10695 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10696 {
10697         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10698         MonoClass *klass;
10699
10700         mono_error_init (error);
10701
10702         MonoType *res = mono_reflection_type_get_handle (type, error);
10703
10704         if (!res && is_ok (error)) {
10705                 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10706         }
10707         return_val_if_nok (error, FALSE);
10708
10709         klass = mono_class_from_mono_type (res);
10710
10711         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10712         mono_domain_lock (domain);
10713
10714         if (!image_is_dynamic (klass->image)) {
10715                 mono_class_setup_supertypes (klass);
10716         } else {
10717                 if (!domain->type_hash)
10718                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10719                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10720                 mono_g_hash_table_insert (domain->type_hash, res, type);
10721         }
10722         mono_domain_unlock (domain);
10723         mono_loader_unlock ();
10724
10725         return TRUE;
10726 }
10727
10728 void
10729 mono_reflection_register_with_runtime (MonoReflectionType *type)
10730 {
10731         MonoError error;
10732         (void) reflection_register_with_runtime (type, &error);
10733         mono_error_set_pending_exception (&error);
10734 }
10735
10736 /**
10737  * LOCKING: Assumes the loader lock is held.
10738  */
10739 static MonoMethodSignature*
10740 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10741         MonoMethodSignature *sig;
10742         int count, i;
10743
10744         mono_error_init (error);
10745
10746         count = parameters? mono_array_length (parameters): 0;
10747
10748         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10749         sig->param_count = count;
10750         sig->sentinelpos = -1; /* FIXME */
10751         for (i = 0; i < count; ++i) {
10752                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10753                 if (!is_ok (error)) {
10754                         image_g_free (image, sig);
10755                         return NULL;
10756                 }
10757         }
10758         return sig;
10759 }
10760
10761 /**
10762  * LOCKING: Assumes the loader lock is held.
10763  */
10764 static MonoMethodSignature*
10765 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10766         MonoMethodSignature *sig;
10767
10768         mono_error_init (error);
10769
10770         sig = parameters_to_signature (image, ctor->parameters, error);
10771         return_val_if_nok (error, NULL);
10772         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10773         sig->ret = &mono_defaults.void_class->byval_arg;
10774         return sig;
10775 }
10776
10777 /**
10778  * LOCKING: Assumes the loader lock is held.
10779  */
10780 static MonoMethodSignature*
10781 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10782         MonoMethodSignature *sig;
10783
10784         mono_error_init (error);
10785
10786         sig = parameters_to_signature (image, method->parameters, error);
10787         return_val_if_nok (error, NULL);
10788         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10789         if (method->rtype) {
10790                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10791                 if (!is_ok (error)) {
10792                         image_g_free (image, sig);
10793                         return NULL;
10794                 }
10795         } else {
10796                 sig->ret = &mono_defaults.void_class->byval_arg;
10797         }
10798         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10799         return sig;
10800 }
10801
10802 static MonoMethodSignature*
10803 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10804         MonoMethodSignature *sig;
10805
10806         mono_error_init (error);
10807
10808         sig = parameters_to_signature (NULL, method->parameters, error);
10809         return_val_if_nok (error, NULL);
10810         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10811         if (method->rtype) {
10812                 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10813                 if (!is_ok (error)) {
10814                         g_free (sig);
10815                         return NULL;
10816                 }
10817         } else {
10818                 sig->ret = &mono_defaults.void_class->byval_arg;
10819         }
10820         sig->generic_param_count = 0;
10821         return sig;
10822 }
10823
10824 static void
10825 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10826 {
10827         mono_error_init (error);
10828         MonoClass *klass = mono_object_class (prop);
10829         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10830                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10831                 *name = mono_string_to_utf8 (pb->name);
10832                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10833         } else {
10834                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10835                 *name = g_strdup (p->property->name);
10836                 if (p->property->get)
10837                         *type = mono_method_signature (p->property->get)->ret;
10838                 else
10839                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10840         }
10841 }
10842
10843 static void
10844 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10845 {
10846         mono_error_init (error);
10847         MonoClass *klass = mono_object_class (field);
10848         if (strcmp (klass->name, "FieldBuilder") == 0) {
10849                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10850                 *name = mono_string_to_utf8 (fb->name);
10851                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10852         } else {
10853                 MonoReflectionField *f = (MonoReflectionField *)field;
10854                 *name = g_strdup (mono_field_get_name (f->field));
10855                 *type = f->field->type;
10856         }
10857 }
10858
10859 #else /* DISABLE_REFLECTION_EMIT */
10860
10861 void
10862 mono_reflection_register_with_runtime (MonoReflectionType *type)
10863 {
10864         /* This is empty */
10865 }
10866
10867 static gboolean
10868 is_sre_type_builder (MonoClass *klass)
10869 {
10870         return FALSE;
10871 }
10872
10873 static gboolean
10874 is_sre_generic_instance (MonoClass *klass)
10875 {
10876         return FALSE;
10877 }
10878
10879 static void
10880 init_type_builder_generics (MonoObject *type)
10881 {
10882 }
10883
10884 #endif /* !DISABLE_REFLECTION_EMIT */
10885
10886
10887 static gboolean
10888 is_sr_mono_field (MonoClass *klass)
10889 {
10890         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10891 }
10892
10893 static gboolean
10894 is_sr_mono_property (MonoClass *klass)
10895 {
10896         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10897 }
10898
10899 static gboolean
10900 is_sr_mono_method (MonoClass *klass)
10901 {
10902         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10903 }
10904
10905 static gboolean
10906 is_sr_mono_cmethod (MonoClass *klass)
10907 {
10908         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10909 }
10910
10911 static gboolean
10912 is_sr_mono_generic_method (MonoClass *klass)
10913 {
10914         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10915 }
10916
10917 static gboolean
10918 is_sr_mono_generic_cmethod (MonoClass *klass)
10919 {
10920         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10921 }
10922
10923 gboolean
10924 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10925 {
10926         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10927 }
10928
10929 static gboolean
10930 is_usertype (MonoReflectionType *ref)
10931 {
10932         MonoClass *klass = mono_object_class (ref);
10933         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10934 }
10935
10936 static MonoReflectionType*
10937 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10938 {
10939         mono_error_init (error);
10940         if (!type || type->type)
10941                 return type;
10942
10943         if (is_usertype (type)) {
10944                 type = mono_reflection_type_get_underlying_system_type (type, error);
10945                 return_val_if_nok (error, NULL);
10946                 if (is_usertype (type)) {
10947                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10948                         return NULL;
10949                 }
10950         }
10951
10952         return type;
10953 }
10954 /**
10955  * encode_cattr_value:
10956  * Encode a value in a custom attribute stream of bytes.
10957  * The value to encode is either supplied as an object in argument val
10958  * (valuetypes are boxed), or as a pointer to the data in the
10959  * argument argval.
10960  * @type represents the type of the value
10961  * @buffer is the start of the buffer
10962  * @p the current position in the buffer
10963  * @buflen contains the size of the buffer and is used to return the new buffer size
10964  * if this needs to be realloced.
10965  * @retbuffer and @retp return the start and the position of the buffer
10966  * @error set on error.
10967  */
10968 static void
10969 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
10970 {
10971         MonoTypeEnum simple_type;
10972         
10973         mono_error_init (error);
10974         if ((p-buffer) + 10 >= *buflen) {
10975                 char *newbuf;
10976                 *buflen *= 2;
10977                 newbuf = (char *)g_realloc (buffer, *buflen);
10978                 p = newbuf + (p-buffer);
10979                 buffer = newbuf;
10980         }
10981         if (!argval)
10982                 argval = ((char*)arg + sizeof (MonoObject));
10983         simple_type = type->type;
10984 handle_enum:
10985         switch (simple_type) {
10986         case MONO_TYPE_BOOLEAN:
10987         case MONO_TYPE_U1:
10988         case MONO_TYPE_I1:
10989                 *p++ = *argval;
10990                 break;
10991         case MONO_TYPE_CHAR:
10992         case MONO_TYPE_U2:
10993         case MONO_TYPE_I2:
10994                 swap_with_size (p, argval, 2, 1);
10995                 p += 2;
10996                 break;
10997         case MONO_TYPE_U4:
10998         case MONO_TYPE_I4:
10999         case MONO_TYPE_R4:
11000                 swap_with_size (p, argval, 4, 1);
11001                 p += 4;
11002                 break;
11003         case MONO_TYPE_R8:
11004                 swap_with_size (p, argval, 8, 1);
11005                 p += 8;
11006                 break;
11007         case MONO_TYPE_U8:
11008         case MONO_TYPE_I8:
11009                 swap_with_size (p, argval, 8, 1);
11010                 p += 8;
11011                 break;
11012         case MONO_TYPE_VALUETYPE:
11013                 if (type->data.klass->enumtype) {
11014                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
11015                         goto handle_enum;
11016                 } else {
11017                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11018                 }
11019                 break;
11020         case MONO_TYPE_STRING: {
11021                 char *str;
11022                 guint32 slen;
11023                 if (!arg) {
11024                         *p++ = 0xFF;
11025                         break;
11026                 }
11027                 str = mono_string_to_utf8 ((MonoString*)arg);
11028                 slen = strlen (str);
11029                 if ((p-buffer) + 10 + slen >= *buflen) {
11030                         char *newbuf;
11031                         *buflen *= 2;
11032                         *buflen += slen;
11033                         newbuf = (char *)g_realloc (buffer, *buflen);
11034                         p = newbuf + (p-buffer);
11035                         buffer = newbuf;
11036                 }
11037                 mono_metadata_encode_value (slen, p, &p);
11038                 memcpy (p, str, slen);
11039                 p += slen;
11040                 g_free (str);
11041                 break;
11042         }
11043         case MONO_TYPE_CLASS: {
11044                 char *str;
11045                 guint32 slen;
11046                 MonoType *arg_type;
11047                 if (!arg) {
11048                         *p++ = 0xFF;
11049                         break;
11050                 }
11051 handle_type:
11052                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11053                 return_if_nok (error);
11054
11055                 str = type_get_qualified_name (arg_type, NULL);
11056                 slen = strlen (str);
11057                 if ((p-buffer) + 10 + slen >= *buflen) {
11058                         char *newbuf;
11059                         *buflen *= 2;
11060                         *buflen += slen;
11061                         newbuf = (char *)g_realloc (buffer, *buflen);
11062                         p = newbuf + (p-buffer);
11063                         buffer = newbuf;
11064                 }
11065                 mono_metadata_encode_value (slen, p, &p);
11066                 memcpy (p, str, slen);
11067                 p += slen;
11068                 g_free (str);
11069                 break;
11070         }
11071         case MONO_TYPE_SZARRAY: {
11072                 int len, i;
11073                 MonoClass *eclass, *arg_eclass;
11074
11075                 if (!arg) {
11076                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11077                         break;
11078                 }
11079                 len = mono_array_length ((MonoArray*)arg);
11080                 *p++ = len & 0xff;
11081                 *p++ = (len >> 8) & 0xff;
11082                 *p++ = (len >> 16) & 0xff;
11083                 *p++ = (len >> 24) & 0xff;
11084                 *retp = p;
11085                 *retbuffer = buffer;
11086                 eclass = type->data.klass;
11087                 arg_eclass = mono_object_class (arg)->element_class;
11088
11089                 if (!eclass) {
11090                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11091                         eclass = mono_defaults.object_class;
11092                 }
11093                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11094                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11095                         int elsize = mono_class_array_element_size (arg_eclass);
11096                         for (i = 0; i < len; ++i) {
11097                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11098                                 return_if_nok (error);
11099                                 elptr += elsize;
11100                         }
11101                 } else if (eclass->valuetype && arg_eclass->valuetype) {
11102                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11103                         int elsize = mono_class_array_element_size (eclass);
11104                         for (i = 0; i < len; ++i) {
11105                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11106                                 return_if_nok (error);
11107                                 elptr += elsize;
11108                         }
11109                 } else {
11110                         for (i = 0; i < len; ++i) {
11111                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11112                                 return_if_nok (error);
11113                         }
11114                 }
11115                 break;
11116         }
11117         case MONO_TYPE_OBJECT: {
11118                 MonoClass *klass;
11119                 char *str;
11120                 guint32 slen;
11121
11122                 /*
11123                  * The parameter type is 'object' but the type of the actual
11124                  * argument is not. So we have to add type information to the blob
11125                  * too. This is completely undocumented in the spec.
11126                  */
11127
11128                 if (arg == NULL) {
11129                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
11130                         *p++ = 0xFF;
11131                         break;
11132                 }
11133                 
11134                 klass = mono_object_class (arg);
11135
11136                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
11137                         *p++ = 0x50;
11138                         goto handle_type;
11139                 } else if (klass->enumtype) {
11140                         *p++ = 0x55;
11141                 } else if (klass == mono_defaults.string_class) {
11142                         simple_type = MONO_TYPE_STRING;
11143                         *p++ = 0x0E;
11144                         goto handle_enum;
11145                 } else if (klass->rank == 1) {
11146                         *p++ = 0x1D;
11147                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11148                                 /* See Partition II, Appendix B3 */
11149                                 *p++ = 0x51;
11150                         else
11151                                 *p++ = klass->element_class->byval_arg.type;
11152                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11153                         return_if_nok (error);
11154                         break;
11155                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11156                         *p++ = simple_type = klass->byval_arg.type;
11157                         goto handle_enum;
11158                 } else {
11159                         g_error ("unhandled type in custom attr");
11160                 }
11161                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11162                 slen = strlen (str);
11163                 if ((p-buffer) + 10 + slen >= *buflen) {
11164                         char *newbuf;
11165                         *buflen *= 2;
11166                         *buflen += slen;
11167                         newbuf = (char *)g_realloc (buffer, *buflen);
11168                         p = newbuf + (p-buffer);
11169                         buffer = newbuf;
11170                 }
11171                 mono_metadata_encode_value (slen, p, &p);
11172                 memcpy (p, str, slen);
11173                 p += slen;
11174                 g_free (str);
11175                 simple_type = mono_class_enum_basetype (klass)->type;
11176                 goto handle_enum;
11177         }
11178         default:
11179                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11180         }
11181         *retp = p;
11182         *retbuffer = buffer;
11183 }
11184
11185 static void
11186 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11187 {
11188         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11189                 char *str = type_get_qualified_name (type, NULL);
11190                 int slen = strlen (str);
11191
11192                 *p++ = 0x55;
11193                 /*
11194                  * This seems to be optional...
11195                  * *p++ = 0x80;
11196                  */
11197                 mono_metadata_encode_value (slen, p, &p);
11198                 memcpy (p, str, slen);
11199                 p += slen;
11200                 g_free (str);
11201         } else if (type->type == MONO_TYPE_OBJECT) {
11202                 *p++ = 0x51;
11203         } else if (type->type == MONO_TYPE_CLASS) {
11204                 /* it should be a type: encode_cattr_value () has the check */
11205                 *p++ = 0x50;
11206         } else {
11207                 mono_metadata_encode_value (type->type, p, &p);
11208                 if (type->type == MONO_TYPE_SZARRAY)
11209                         /* See the examples in Partition VI, Annex B */
11210                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11211         }
11212
11213         *retp = p;
11214 }
11215
11216 #ifndef DISABLE_REFLECTION_EMIT
11217 static void
11218 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11219 {
11220         int len;
11221
11222         mono_error_init (error);
11223
11224         /* Preallocate a large enough buffer */
11225         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11226                 char *str = type_get_qualified_name (type, NULL);
11227                 len = strlen (str);
11228                 g_free (str);
11229         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11230                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11231                 len = strlen (str);
11232                 g_free (str);
11233         } else {
11234                 len = 0;
11235         }
11236         len += strlen (name);
11237
11238         if ((p-buffer) + 20 + len >= *buflen) {
11239                 char *newbuf;
11240                 *buflen *= 2;
11241                 *buflen += len;
11242                 newbuf = (char *)g_realloc (buffer, *buflen);
11243                 p = newbuf + (p-buffer);
11244                 buffer = newbuf;
11245         }
11246
11247         encode_field_or_prop_type (type, p, &p);
11248
11249         len = strlen (name);
11250         mono_metadata_encode_value (len, p, &p);
11251         memcpy (p, name, len);
11252         p += len;
11253         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11254         return_if_nok (error);
11255         *retp = p;
11256         *retbuffer = buffer;
11257 }
11258
11259 /**
11260  * mono_reflection_get_custom_attrs_blob:
11261  * @ctor: custom attribute constructor
11262  * @ctorArgs: arguments o the constructor
11263  * @properties:
11264  * @propValues:
11265  * @fields:
11266  * @fieldValues:
11267  * 
11268  * Creates the blob of data that needs to be saved in the metadata and that represents
11269  * the custom attributed described by @ctor, @ctorArgs etc.
11270  * Returns: a Byte array representing the blob of data.
11271  */
11272 MonoArray*
11273 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11274 {
11275         MonoError error;
11276         MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11277         mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
11278         return result;
11279 }
11280
11281 /**
11282  * mono_reflection_get_custom_attrs_blob_checked:
11283  * @ctor: custom attribute constructor
11284  * @ctorArgs: arguments o the constructor
11285  * @properties:
11286  * @propValues:
11287  * @fields:
11288  * @fieldValues:
11289  * @error: set on error
11290  * 
11291  * Creates the blob of data that needs to be saved in the metadata and that represents
11292  * the custom attributed described by @ctor, @ctorArgs etc.
11293  * Returns: a Byte array representing the blob of data.  On failure returns NULL and sets @error.
11294  */
11295 MonoArray*
11296 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error) 
11297 {
11298         MonoArray *result = NULL;
11299         MonoMethodSignature *sig;
11300         MonoObject *arg;
11301         char *buffer, *p;
11302         guint32 buflen, i;
11303
11304         mono_error_init (error);
11305
11306         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11307                 /* sig is freed later so allocate it in the heap */
11308                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11309                 if (!is_ok (error)) {
11310                         g_free (sig);
11311                         return NULL;
11312                 }
11313         } else {
11314                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11315         }
11316
11317         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11318         buflen = 256;
11319         p = buffer = (char *)g_malloc (buflen);
11320         /* write the prolog */
11321         *p++ = 1;
11322         *p++ = 0;
11323         for (i = 0; i < sig->param_count; ++i) {
11324                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11325                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11326                 if (!is_ok (error)) goto leave;
11327         }
11328         i = 0;
11329         if (properties)
11330                 i += mono_array_length (properties);
11331         if (fields)
11332                 i += mono_array_length (fields);
11333         *p++ = i & 0xff;
11334         *p++ = (i >> 8) & 0xff;
11335         if (properties) {
11336                 MonoObject *prop;
11337                 for (i = 0; i < mono_array_length (properties); ++i) {
11338                         MonoType *ptype;
11339                         char *pname;
11340
11341                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11342                         get_prop_name_and_type (prop, &pname, &ptype, error);
11343                         if (!is_ok (error)) goto leave;
11344                         *p++ = 0x54; /* PROPERTY signature */
11345                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11346                         g_free (pname);
11347                         if (!is_ok (error)) goto leave;
11348                 }
11349         }
11350
11351         if (fields) {
11352                 MonoObject *field;
11353                 for (i = 0; i < mono_array_length (fields); ++i) {
11354                         MonoType *ftype;
11355                         char *fname;
11356
11357                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11358                         get_field_name_and_type (field, &fname, &ftype, error);
11359                         if (!is_ok (error)) goto leave;
11360                         *p++ = 0x53; /* FIELD signature */
11361                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11362                         g_free (fname);
11363                         if (!is_ok (error)) goto leave;
11364                 }
11365         }
11366
11367         g_assert (p - buffer <= buflen);
11368         buflen = p - buffer;
11369         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11370         p = mono_array_addr (result, char, 0);
11371         memcpy (p, buffer, buflen);
11372 leave:
11373         g_free (buffer);
11374         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11375                 g_free (sig);
11376         return result;
11377 }
11378
11379 /**
11380  * reflection_setup_internal_class:
11381  * @tb: a TypeBuilder object
11382  * @error: set on error
11383  *
11384  * Creates a MonoClass that represents the TypeBuilder.
11385  * This is a trick that lets us simplify a lot of reflection code
11386  * (and will allow us to support Build and Run assemblies easier).
11387  *
11388  * Returns TRUE on success. On failure, returns FALSE and sets @error.
11389  */
11390 static gboolean
11391 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11392 {
11393         MonoClass *klass, *parent;
11394
11395         mono_error_init (error);
11396         RESOLVE_TYPE (tb->parent, error);
11397         return_val_if_nok (error, FALSE);
11398
11399         mono_loader_lock ();
11400
11401         if (tb->parent) {
11402                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11403                 if (!is_ok (error)) {
11404                         mono_loader_unlock ();
11405                         return FALSE;
11406                 }
11407                 /* check so we can compile corlib correctly */
11408                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11409                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11410                         parent = parent_type->data.klass;
11411                 } else {
11412                         parent = mono_class_from_mono_type (parent_type);
11413                 }
11414         } else {
11415                 parent = NULL;
11416         }
11417         
11418         /* the type has already being created: it means we just have to change the parent */
11419         if (tb->type.type) {
11420                 klass = mono_class_from_mono_type (tb->type.type);
11421                 klass->parent = NULL;
11422                 /* fool mono_class_setup_parent */
11423                 klass->supertypes = NULL;
11424                 mono_class_setup_parent (klass, parent);
11425                 mono_class_setup_mono_type (klass);
11426                 mono_loader_unlock ();
11427                 return TRUE;
11428         }
11429
11430         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11431
11432         klass->image = &tb->module->dynamic_image->image;
11433
11434         klass->inited = 1; /* we lie to the runtime */
11435         klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11436         if (!is_ok (error))
11437                 goto failure;
11438         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11439         if (!is_ok (error))
11440                 goto failure;
11441         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11442         klass->flags = tb->attrs;
11443         
11444         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11445
11446         klass->element_class = klass;
11447
11448         if (mono_class_get_ref_info (klass) == NULL) {
11449
11450                 mono_class_set_ref_info (klass, tb);
11451
11452                 /* Put into cache so mono_class_get_checked () will find it.
11453                 Skip nested types as those should not be available on the global scope. */
11454                 if (!tb->nesting_type)
11455                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11456
11457                 /*
11458                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11459                 by performing a mono_class_get which does the full resolution.
11460
11461                 Working around this semantics would require us to write a lot of code for no clear advantage.
11462                 */
11463                 mono_image_append_class_to_reflection_info_set (klass);
11464         } else {
11465                 g_assert (mono_class_get_ref_info (klass) == tb);
11466         }
11467
11468         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11469
11470         if (parent != NULL) {
11471                 mono_class_setup_parent (klass, parent);
11472         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11473                 const char *old_n = klass->name;
11474                 /* trick to get relative numbering right when compiling corlib */
11475                 klass->name = "BuildingObject";
11476                 mono_class_setup_parent (klass, mono_defaults.object_class);
11477                 klass->name = old_n;
11478         }
11479
11480         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11481                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11482                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11483                 klass->instance_size = sizeof (MonoObject);
11484                 klass->size_inited = 1;
11485                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11486         }
11487
11488         mono_class_setup_mono_type (klass);
11489
11490         mono_class_setup_supertypes (klass);
11491
11492         /*
11493          * FIXME: handle interfaces.
11494          */
11495
11496         tb->type.type = &klass->byval_arg;
11497
11498         if (tb->nesting_type) {
11499                 g_assert (tb->nesting_type->type);
11500                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11501                 if (!is_ok (error)) goto failure;
11502                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11503         }
11504
11505         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11506
11507         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11508         
11509         mono_loader_unlock ();
11510         return TRUE;
11511
11512 failure:
11513         mono_loader_unlock ();
11514         return FALSE;
11515 }
11516
11517 /**
11518  * mono_reflection_setup_internal_class:
11519  * @tb: a TypeBuilder object
11520  *
11521  * (icall)
11522  * Creates a MonoClass that represents the TypeBuilder.
11523  * This is a trick that lets us simplify a lot of reflection code
11524  * (and will allow us to support Build and Run assemblies easier).
11525  *
11526  */
11527 void
11528 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11529 {
11530         MonoError error;
11531         (void) reflection_setup_internal_class (tb, &error);
11532         mono_error_set_pending_exception (&error);
11533 }
11534
11535 /*
11536  * mono_reflection_setup_generic_class:
11537  * @tb: a TypeBuilder object
11538  *
11539  * Setup the generic class before adding the first generic parameter.
11540  */
11541 void
11542 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11543 {
11544 }
11545
11546 /*
11547  * mono_reflection_create_generic_class:
11548  * @tb: a TypeBuilder object
11549  *
11550  * Creates the generic class after all generic parameters have been added.
11551  */
11552 void
11553 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11554 {
11555         MonoError error;
11556         MonoClass *klass;
11557         int count, i;
11558
11559         klass = mono_class_from_mono_type (tb->type.type);
11560
11561         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11562
11563         if (klass->generic_container || (count == 0))
11564                 return;
11565
11566         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11567
11568         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11569
11570         klass->generic_container->owner.klass = klass;
11571         klass->generic_container->type_argc = count;
11572         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11573
11574         klass->is_generic = 1;
11575
11576         for (i = 0; i < count; i++) {
11577                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11578                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11579                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11580                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11581                 klass->generic_container->type_params [i] = *param;
11582                 /*Make sure we are a diferent type instance */
11583                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11584                 klass->generic_container->type_params [i].info.pklass = NULL;
11585                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11586
11587                 g_assert (klass->generic_container->type_params [i].param.owner);
11588         }
11589
11590         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11591 }
11592
11593 /**
11594  * reflection_create_internal_class:
11595  * @tb: a TypeBuilder object
11596  * @error: set on error
11597  *
11598  * Actually create the MonoClass that is associated with the TypeBuilder.
11599  * On success returns TRUE, on failure returns FALSE and sets @error.
11600  *
11601  */
11602 static gboolean
11603 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11604 {
11605
11606         MonoClass *klass;
11607
11608         mono_error_init (error);
11609         klass = mono_class_from_mono_type (tb->type.type);
11610
11611         mono_loader_lock ();
11612         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11613                 MonoReflectionFieldBuilder *fb;
11614                 MonoClass *ec;
11615                 MonoType *enum_basetype;
11616
11617                 g_assert (tb->fields != NULL);
11618                 g_assert (mono_array_length (tb->fields) >= 1);
11619
11620                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11621
11622                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11623                 if (!is_ok (error)) {
11624                         mono_loader_unlock ();
11625                         return FALSE;
11626                 }
11627                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11628                         mono_loader_unlock ();
11629                         return TRUE;
11630                 }
11631
11632                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11633                 if (!is_ok (error)) {
11634                         mono_loader_unlock ();
11635                         return FALSE;
11636                 }
11637                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11638                 if (!klass->element_class)
11639                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11640
11641                 /*
11642                  * get the element_class from the current corlib.
11643                  */
11644                 ec = default_class_from_mono_type (enum_basetype);
11645                 klass->instance_size = ec->instance_size;
11646                 klass->size_inited = 1;
11647                 /* 
11648                  * this is almost safe to do with enums and it's needed to be able
11649                  * to create objects of the enum type (for use in SetConstant).
11650                  */
11651                 /* FIXME: Does this mean enums can't have method overrides ? */
11652                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11653         }
11654         mono_loader_unlock ();
11655         return TRUE;
11656 }
11657
11658 /**
11659  * mono_reflection_create_internal_class:
11660  * @tb: a TypeBuilder object
11661  *
11662  * (icall)
11663  * Actually create the MonoClass that is associated with the TypeBuilder.
11664  */
11665 void
11666 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11667 {
11668         MonoError error;
11669         (void) reflection_create_internal_class (tb, &error);
11670         mono_error_set_pending_exception (&error);
11671 }
11672
11673 static MonoMarshalSpec*
11674 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11675                                 MonoReflectionMarshal *minfo, MonoError *error)
11676 {
11677         MonoMarshalSpec *res;
11678
11679         mono_error_init (error);
11680
11681         res = image_g_new0 (image, MonoMarshalSpec, 1);
11682         res->native = (MonoMarshalNative)minfo->type;
11683
11684         switch (minfo->type) {
11685         case MONO_NATIVE_LPARRAY:
11686                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11687                 if (minfo->has_size) {
11688                         res->data.array_data.param_num = minfo->param_num;
11689                         res->data.array_data.num_elem = minfo->count;
11690                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11691                 }
11692                 else {
11693                         res->data.array_data.param_num = -1;
11694                         res->data.array_data.num_elem = -1;
11695                         res->data.array_data.elem_mult = -1;
11696                 }
11697                 break;
11698
11699         case MONO_NATIVE_BYVALTSTR:
11700         case MONO_NATIVE_BYVALARRAY:
11701                 res->data.array_data.num_elem = minfo->count;
11702                 break;
11703
11704         case MONO_NATIVE_CUSTOM:
11705                 if (minfo->marshaltyperef) {
11706                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11707                         if (!is_ok (error)) {
11708                                 image_g_free (image, res);
11709                                 return NULL;
11710                         }
11711                         res->data.custom_data.custom_name =
11712                                 type_get_fully_qualified_name (marshaltyperef);
11713                 }
11714                 if (minfo->mcookie)
11715                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11716                 break;
11717
11718         default:
11719                 break;
11720         }
11721
11722         return res;
11723 }
11724 #endif /* !DISABLE_REFLECTION_EMIT */
11725
11726 MonoReflectionMarshalAsAttribute*
11727 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11728                                                         MonoMarshalSpec *spec, MonoError *error)
11729 {
11730         MonoReflectionType *rt;
11731         MonoReflectionMarshalAsAttribute *minfo;
11732         MonoType *mtype;
11733
11734         mono_error_init (error);
11735         
11736         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11737         if (!minfo)
11738                 return NULL;
11739         minfo->utype = spec->native;
11740
11741         switch (minfo->utype) {
11742         case MONO_NATIVE_LPARRAY:
11743                 minfo->array_subtype = spec->data.array_data.elem_type;
11744                 minfo->size_const = spec->data.array_data.num_elem;
11745                 if (spec->data.array_data.param_num != -1)
11746                         minfo->size_param_index = spec->data.array_data.param_num;
11747                 break;
11748
11749         case MONO_NATIVE_BYVALTSTR:
11750         case MONO_NATIVE_BYVALARRAY:
11751                 minfo->size_const = spec->data.array_data.num_elem;
11752                 break;
11753
11754         case MONO_NATIVE_CUSTOM:
11755                 if (spec->data.custom_data.custom_name) {
11756                         mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11757                         return_val_if_nok  (error, NULL);
11758
11759                         if (mtype) {
11760                                 rt = mono_type_get_object_checked (domain, mtype, error);
11761                                 if (!rt)
11762                                         return NULL;
11763
11764                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11765                         }
11766
11767                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11768                 }
11769                 if (spec->data.custom_data.cookie)
11770                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11771                 break;
11772
11773         default:
11774                 break;
11775         }
11776
11777         return minfo;
11778 }
11779
11780 #ifndef DISABLE_REFLECTION_EMIT
11781 static MonoMethod*
11782 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11783                                          ReflectionMethodBuilder *rmb,
11784                                          MonoMethodSignature *sig)
11785 {
11786         MonoError error;
11787         MonoMethod *m;
11788         MonoMethodWrapper *wrapperm;
11789         MonoMarshalSpec **specs;
11790         MonoReflectionMethodAux *method_aux;
11791         MonoImage *image;
11792         gboolean dynamic;
11793         int i;
11794
11795         mono_error_init (&error);
11796         /*
11797          * Methods created using a MethodBuilder should have their memory allocated
11798          * inside the image mempool, while dynamic methods should have their memory
11799          * malloc'd.
11800          */
11801         dynamic = rmb->refs != NULL;
11802         image = dynamic ? NULL : klass->image;
11803
11804         if (!dynamic)
11805                 g_assert (!klass->generic_class);
11806
11807         mono_loader_lock ();
11808
11809         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11810                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11811                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11812         else
11813                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11814
11815         wrapperm = (MonoMethodWrapper*)m;
11816
11817         m->dynamic = dynamic;
11818         m->slot = -1;
11819         m->flags = rmb->attrs;
11820         m->iflags = rmb->iattrs;
11821         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11822         m->klass = klass;
11823         m->signature = sig;
11824         m->sre_method = TRUE;
11825         m->skip_visibility = rmb->skip_visibility;
11826         if (rmb->table_idx)
11827                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11828
11829         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11830                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11831                         m->string_ctor = 1;
11832
11833                 m->signature->pinvoke = 1;
11834         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11835                 m->signature->pinvoke = 1;
11836
11837                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11838
11839                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11840                 g_assert (mono_error_ok (&error));
11841                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11842                 g_assert (mono_error_ok (&error));
11843                 
11844                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11845
11846                 if (image_is_dynamic (klass->image))
11847                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11848
11849                 mono_loader_unlock ();
11850
11851                 return m;
11852         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11853                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11854                 MonoMethodHeader *header;
11855                 guint32 code_size;
11856                 gint32 max_stack, i;
11857                 gint32 num_locals = 0;
11858                 gint32 num_clauses = 0;
11859                 guint8 *code;
11860
11861                 if (rmb->ilgen) {
11862                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11863                         code_size = rmb->ilgen->code_len;
11864                         max_stack = rmb->ilgen->max_stack;
11865                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11866                         if (rmb->ilgen->ex_handlers)
11867                                 num_clauses = method_count_clauses (rmb->ilgen);
11868                 } else {
11869                         if (rmb->code) {
11870                                 code = mono_array_addr (rmb->code, guint8, 0);
11871                                 code_size = mono_array_length (rmb->code);
11872                                 /* we probably need to run a verifier on the code... */
11873                                 max_stack = 8; 
11874                         }
11875                         else {
11876                                 code = NULL;
11877                                 code_size = 0;
11878                                 max_stack = 8;
11879                         }
11880                 }
11881
11882                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11883                 header->code_size = code_size;
11884                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11885                 memcpy ((char*)header->code, code, code_size);
11886                 header->max_stack = max_stack;
11887                 header->init_locals = rmb->init_locals;
11888                 header->num_locals = num_locals;
11889
11890                 for (i = 0; i < num_locals; ++i) {
11891                         MonoReflectionLocalBuilder *lb = 
11892                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11893
11894                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11895                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11896                         mono_error_assert_ok (&error);
11897                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11898                 }
11899
11900                 header->num_clauses = num_clauses;
11901                 if (num_clauses) {
11902                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11903                                                                  rmb->ilgen, num_clauses, &error);
11904                         mono_error_assert_ok (&error);
11905                 }
11906
11907                 wrapperm->header = header;
11908         }
11909
11910         if (rmb->generic_params) {
11911                 int count = mono_array_length (rmb->generic_params);
11912                 MonoGenericContainer *container = rmb->generic_container;
11913
11914                 g_assert (container);
11915
11916                 container->type_argc = count;
11917                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11918                 container->owner.method = m;
11919                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11920
11921                 m->is_generic = TRUE;
11922                 mono_method_set_generic_container (m, container);
11923
11924                 for (i = 0; i < count; i++) {
11925                         MonoReflectionGenericParam *gp =
11926                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11927                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11928                         mono_error_assert_ok (&error);
11929                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11930                         container->type_params [i] = *param;
11931                 }
11932
11933                 /*
11934                  * The method signature might have pointers to generic parameters that belong to other methods.
11935                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11936                  * generic parameters.
11937                  */
11938                 for (i = 0; i < m->signature->param_count; ++i) {
11939                         MonoType *t = m->signature->params [i];
11940                         if (t->type == MONO_TYPE_MVAR) {
11941                                 MonoGenericParam *gparam =  t->data.generic_param;
11942                                 if (gparam->num < count) {
11943                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11944                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11945                                 }
11946
11947                         }
11948                 }
11949
11950                 if (klass->generic_container) {
11951                         container->parent = klass->generic_container;
11952                         container->context.class_inst = klass->generic_container->context.class_inst;
11953                 }
11954                 container->context.method_inst = mono_get_shared_generic_inst (container);
11955         }
11956
11957         if (rmb->refs) {
11958                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11959                 int i;
11960                 void **data;
11961
11962                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11963
11964                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11965                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11966                 for (i = 0; i < rmb->nrefs; ++i)
11967                         data [i + 1] = rmb->refs [i];
11968         }
11969
11970         method_aux = NULL;
11971
11972         /* Parameter info */
11973         if (rmb->pinfo) {
11974                 if (!method_aux)
11975                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11976                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11977                 for (i = 0; i <= m->signature->param_count; ++i) {
11978                         MonoReflectionParamBuilder *pb;
11979                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11980                                 if ((i > 0) && (pb->attrs)) {
11981                                         /* Make a copy since it might point to a shared type structure */
11982                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11983                                         m->signature->params [i - 1]->attrs = pb->attrs;
11984                                 }
11985
11986                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11987                                         MonoDynamicImage *assembly;
11988                                         guint32 idx, len;
11989                                         MonoTypeEnum def_type;
11990                                         char *p;
11991                                         const char *p2;
11992
11993                                         if (!method_aux->param_defaults) {
11994                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11995                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11996                                         }
11997                                         assembly = (MonoDynamicImage*)klass->image;
11998                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11999                                         /* Copy the data from the blob since it might get realloc-ed */
12000                                         p = assembly->blob.data + idx;
12001                                         len = mono_metadata_decode_blob_size (p, &p2);
12002                                         len += p2 - p;
12003                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12004                                         method_aux->param_default_types [i] = def_type;
12005                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12006                                 }
12007
12008                                 if (pb->name) {
12009                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
12010                                         g_assert (mono_error_ok (&error));
12011                                 }
12012                                 if (pb->cattrs) {
12013                                         if (!method_aux->param_cattr)
12014                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12015                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12016                                 }
12017                         }
12018                 }
12019         }
12020
12021         /* Parameter marshalling */
12022         specs = NULL;
12023         if (rmb->pinfo)         
12024                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12025                         MonoReflectionParamBuilder *pb;
12026                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12027                                 if (pb->marshal_info) {
12028                                         if (specs == NULL)
12029                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12030                                         specs [pb->position] = 
12031                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, &error);
12032                                         if (!is_ok (&error)) {
12033                                                 mono_loader_unlock ();
12034                                                 image_g_free (image, specs);
12035                                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12036                                         }
12037                                 }
12038                         }
12039                 }
12040         if (specs != NULL) {
12041                 if (!method_aux)
12042                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12043                 method_aux->param_marshall = specs;
12044         }
12045
12046         if (image_is_dynamic (klass->image) && method_aux)
12047                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12048
12049         mono_loader_unlock ();
12050
12051         return m;
12052 }       
12053
12054 static MonoMethod*
12055 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12056 {
12057         ReflectionMethodBuilder rmb;
12058         MonoMethodSignature *sig;
12059
12060         mono_loader_lock ();
12061         g_assert (klass->image != NULL);
12062         sig = ctor_builder_to_signature (klass->image, mb, error);
12063         mono_loader_unlock ();
12064         return_val_if_nok (error, NULL);
12065
12066         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12067                 return NULL;
12068
12069         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12070         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12071
12072         /* If we are in a generic class, we might be called multiple times from inflate_method */
12073         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12074                 /* ilgen is no longer needed */
12075                 mb->ilgen = NULL;
12076         }
12077
12078         return mb->mhandle;
12079 }
12080
12081 static MonoMethod*
12082 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12083 {
12084         ReflectionMethodBuilder rmb;
12085         MonoMethodSignature *sig;
12086
12087         mono_error_init (error);
12088
12089         mono_loader_lock ();
12090         g_assert (klass->image != NULL);
12091         sig = method_builder_to_signature (klass->image, mb, error);
12092         mono_loader_unlock ();
12093         return_val_if_nok (error, NULL);
12094
12095         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12096                 return NULL;
12097
12098         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12099         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12100
12101         /* If we are in a generic class, we might be called multiple times from inflate_method */
12102         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12103                 /* ilgen is no longer needed */
12104                 mb->ilgen = NULL;
12105         }
12106         return mb->mhandle;
12107 }
12108
12109 static MonoClassField*
12110 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12111 {
12112         MonoClassField *field;
12113         MonoType *custom;
12114
12115         mono_error_init (error);
12116
12117         field = g_new0 (MonoClassField, 1);
12118
12119         field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12120         mono_error_assert_ok (error);
12121         if (fb->attrs || fb->modreq || fb->modopt) {
12122                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12123                 if (!is_ok (error)) {
12124                         g_free (field);
12125                         return NULL;
12126                 }
12127                 field->type = mono_metadata_type_dup (NULL, type);
12128                 field->type->attrs = fb->attrs;
12129
12130                 g_assert (image_is_dynamic (klass->image));
12131                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12132                 g_free (field->type);
12133                 if (!is_ok (error)) {
12134                         g_free (field);
12135                         return NULL;
12136                 }
12137                 field->type = mono_metadata_type_dup (klass->image, custom);
12138                 g_free (custom);
12139         } else {
12140                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12141                 if (!is_ok (error)) {
12142                         g_free (field);
12143                         return NULL;
12144                 }
12145         }
12146         if (fb->offset != -1)
12147                 field->offset = fb->offset;
12148         field->parent = klass;
12149         mono_save_custom_attrs (klass->image, field, fb->cattrs);
12150
12151         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12152
12153         return field;
12154 }
12155 #endif
12156
12157 /**
12158  * mono_reflection_bind_generic_parameters:
12159  * @type: a managed type object (which should be some kind of generic (instance? definition?))
12160  * @type_args: the number of type arguments to bind
12161  * @types: array of type arguments
12162  * @error: set on error
12163  *
12164  * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12165  * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
12166  */
12167 MonoType*
12168 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12169 {
12170         MonoClass *klass;
12171         MonoReflectionTypeBuilder *tb = NULL;
12172         gboolean is_dynamic = FALSE;
12173         MonoClass *geninst;
12174
12175         mono_error_init (error);
12176         
12177         mono_loader_lock ();
12178
12179         if (is_sre_type_builder (mono_object_class (type))) {
12180                 tb = (MonoReflectionTypeBuilder *) type;
12181
12182                 is_dynamic = TRUE;
12183         } else if (is_sre_generic_instance (mono_object_class (type))) {
12184                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12185                 MonoReflectionType *gtd = rgi->generic_type;
12186
12187                 if (is_sre_type_builder (mono_object_class (gtd))) {
12188                         tb = (MonoReflectionTypeBuilder *)gtd;
12189                         is_dynamic = TRUE;
12190                 }
12191         }
12192
12193         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12194         if (tb && tb->generic_container)
12195                 mono_reflection_create_generic_class (tb);
12196
12197         MonoType *t = mono_reflection_type_get_handle (type, error);
12198         if (!is_ok (error)) {
12199                 mono_loader_unlock ();
12200                 return NULL;
12201         }
12202
12203         klass = mono_class_from_mono_type (t);
12204         if (!klass->generic_container) {
12205                 mono_loader_unlock ();
12206                 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12207                 return NULL;
12208         }
12209
12210         if (klass->wastypebuilder) {
12211                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12212
12213                 is_dynamic = TRUE;
12214         }
12215
12216         mono_loader_unlock ();
12217
12218         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12219
12220         return &geninst->byval_arg;
12221 }
12222
12223 MonoClass*
12224 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12225 {
12226         MonoGenericClass *gclass;
12227         MonoGenericInst *inst;
12228
12229         g_assert (klass->generic_container);
12230
12231         inst = mono_metadata_get_generic_inst (type_argc, types);
12232         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12233
12234         return mono_generic_class_get_class (gclass);
12235 }
12236
12237 MonoReflectionMethod*
12238 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12239 {
12240         MonoError error;
12241         MonoClass *klass;
12242         MonoMethod *method, *inflated;
12243         MonoMethodInflated *imethod;
12244         MonoGenericContext tmp_context;
12245         MonoGenericInst *ginst;
12246         MonoType **type_argv;
12247         int count, i;
12248
12249         /*FIXME but this no longer should happen*/
12250         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12251 #ifndef DISABLE_REFLECTION_EMIT
12252                 MonoReflectionMethodBuilder *mb = NULL;
12253                 MonoType *tb;
12254                 MonoClass *klass;
12255
12256                 mb = (MonoReflectionMethodBuilder *) rmethod;
12257                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
12258                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12259                 klass = mono_class_from_mono_type (tb);
12260
12261                 method = methodbuilder_to_mono_method (klass, mb, &error);
12262                 if (!method)
12263                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12264 #else
12265                 g_assert_not_reached ();
12266                 method = NULL;
12267 #endif
12268         } else {
12269                 method = rmethod->method;
12270         }
12271
12272         klass = method->klass;
12273
12274         if (method->is_inflated)
12275                 method = ((MonoMethodInflated *) method)->declaring;
12276
12277         count = mono_method_signature (method)->generic_param_count;
12278         if (count != mono_array_length (types))
12279                 return NULL;
12280
12281         type_argv = g_new0 (MonoType *, count);
12282         for (i = 0; i < count; i++) {
12283                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12284                 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
12285                 if (!is_ok (&error)) {
12286                         g_free (type_argv);
12287                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12288                 }
12289         }
12290         ginst = mono_metadata_get_generic_inst (count, type_argv);
12291         g_free (type_argv);
12292
12293         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12294         tmp_context.method_inst = ginst;
12295
12296         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
12297         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12298         imethod = (MonoMethodInflated *) inflated;
12299
12300         /*FIXME but I think this is no longer necessary*/
12301         if (image_is_dynamic (method->klass->image)) {
12302                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12303                 /*
12304                  * This table maps metadata structures representing inflated methods/fields
12305                  * to the reflection objects representing their generic definitions.
12306                  */
12307                 mono_image_lock ((MonoImage*)image);
12308                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12309                 mono_image_unlock ((MonoImage*)image);
12310         }
12311
12312         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12313                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12314         
12315         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12316         mono_error_raise_exception (&error); /* FIXME don't raise here */
12317         return ret;
12318 }
12319
12320 #ifndef DISABLE_REFLECTION_EMIT
12321
12322 static MonoMethod *
12323 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12324 {
12325         MonoMethodInflated *imethod;
12326         MonoGenericContext *context;
12327         int i;
12328
12329         /*
12330          * With generic code sharing the klass might not be inflated.
12331          * This can happen because classes inflated with their own
12332          * type arguments are "normalized" to the uninflated class.
12333          */
12334         if (!klass->generic_class)
12335                 return method;
12336
12337         context = mono_class_get_context (klass);
12338
12339         if (klass->method.count && klass->methods) {
12340                 /* Find the already created inflated method */
12341                 for (i = 0; i < klass->method.count; ++i) {
12342                         g_assert (klass->methods [i]->is_inflated);
12343                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12344                                 break;
12345                 }
12346                 g_assert (i < klass->method.count);
12347                 imethod = (MonoMethodInflated*)klass->methods [i];
12348         } else {
12349                 MonoError error;
12350                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12351                 mono_error_assert_ok (&error);
12352         }
12353
12354         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12355                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12356
12357                 mono_image_lock ((MonoImage*)image);
12358                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12359                 mono_image_unlock ((MonoImage*)image);
12360         }
12361         return (MonoMethod *) imethod;
12362 }
12363
12364 static MonoMethod *
12365 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12366 {
12367         MonoMethod *method;
12368         MonoClass *gklass;
12369
12370         mono_error_init (error);
12371
12372         MonoClass *type_class = mono_object_class (type);
12373
12374         if (is_sre_generic_instance (type_class)) {
12375                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12376                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12377                 return_val_if_nok (error, NULL);
12378                 gklass = mono_class_from_mono_type (generic_type);
12379         } else if (is_sre_type_builder (type_class)) {
12380                 MonoType *t = mono_reflection_type_get_handle (type, error);
12381                 return_val_if_nok (error, NULL);
12382                 gklass = mono_class_from_mono_type (t);
12383         } else if (type->type) {
12384                 gklass = mono_class_from_mono_type (type->type);
12385                 gklass = mono_class_get_generic_type_definition (gklass);
12386         } else {
12387                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12388         }
12389
12390         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12391                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12392                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12393                 else {
12394                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12395                         if (!method)
12396                                 return NULL;
12397                 }
12398         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12399                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12400                 if (!method)
12401                         return NULL;
12402         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12403                 method = ((MonoReflectionMethod *) obj)->method;
12404         else {
12405                 method = NULL; /* prevent compiler warning */
12406                 g_error ("can't handle type %s", obj->vtable->klass->name);
12407         }
12408
12409         MonoType *t = mono_reflection_type_get_handle (type, error);
12410         return_val_if_nok (error, NULL);
12411         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12412 }
12413
12414 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12415 static gboolean
12416 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12417 {
12418         MonoGenericClass *gclass;
12419         MonoDynamicGenericClass *dgclass;
12420         MonoClass *klass, *gklass;
12421         MonoType *gtype;
12422         int i;
12423
12424         mono_error_init (error);
12425
12426         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12427         return_val_if_nok (error, FALSE);
12428         klass = mono_class_from_mono_type (gtype);
12429         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12430         gclass = gtype->data.generic_class;
12431
12432         if (!gclass->is_dynamic)
12433                 return TRUE;
12434
12435         dgclass = (MonoDynamicGenericClass *) gclass;
12436
12437         if (dgclass->initialized)
12438                 return TRUE;
12439
12440         gklass = gclass->container_class;
12441         mono_class_init (gklass);
12442
12443         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12444
12445         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12446         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12447         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12448
12449         for (i = 0; i < dgclass->count_fields; i++) {
12450                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12451                 MonoClassField *field, *inflated_field = NULL;
12452
12453                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12454                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12455                         return_val_if_nok (error, FALSE);
12456                 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12457                         field = ((MonoReflectionField *) obj)->field;
12458                 else {
12459                         field = NULL; /* prevent compiler warning */
12460                         g_assert_not_reached ();
12461                 }
12462
12463                 dgclass->fields [i] = *field;
12464                 dgclass->fields [i].parent = klass;
12465                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12466                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12467                 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12468                 dgclass->field_generic_types [i] = field->type;
12469                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12470                 dgclass->field_objects [i] = obj;
12471
12472                 if (inflated_field) {
12473                         g_free (inflated_field);
12474                 } else {
12475                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12476                 }
12477         }
12478
12479         dgclass->initialized = TRUE;
12480         return TRUE;
12481 }
12482
12483 void
12484 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12485 {
12486         MonoError error;
12487         (void) reflection_generic_class_initialize (type, fields, &error);
12488         mono_error_set_pending_exception (&error);
12489 }
12490
12491 void
12492 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12493 {
12494         MonoDynamicGenericClass *dgclass;
12495         int i;
12496
12497         g_assert (gclass->is_dynamic);
12498
12499         dgclass = (MonoDynamicGenericClass *)gclass;
12500
12501         for (i = 0; i < dgclass->count_fields; ++i) {
12502                 MonoClassField *field = dgclass->fields + i;
12503                 mono_metadata_free_type (field->type);
12504                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12505         }
12506 }
12507
12508 /**
12509  * fix_partial_generic_class:
12510  * @klass: a generic instantiation MonoClass
12511  * @error: set on error
12512  *
12513  * Assumes that the generic container of @klass has its vtable
12514  * initialized, and updates the parent class, insterfaces, methods and
12515  * fields of @klass by inflating the types using the generic context.
12516  *
12517  * On success returns TRUE, on failure returns FALSE and sets @error.
12518  *
12519  */
12520 static gboolean
12521 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12522 {
12523         MonoClass *gklass = klass->generic_class->container_class;
12524         MonoDynamicGenericClass *dgclass;
12525         int i;
12526
12527         mono_error_init (error);
12528
12529         if (klass->wastypebuilder)
12530                 return TRUE;
12531
12532         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12533         if (klass->parent != gklass->parent) {
12534                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12535                 if (mono_error_ok (error)) {
12536                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12537                         mono_metadata_free_type (parent_type);
12538                         if (parent != klass->parent) {
12539                                 /*fool mono_class_setup_parent*/
12540                                 klass->supertypes = NULL;
12541                                 mono_class_setup_parent (klass, parent);
12542                         }
12543                 } else {
12544                         if (gklass->wastypebuilder)
12545                                 klass->wastypebuilder = TRUE;
12546                         return FALSE;
12547                 }
12548         }
12549
12550         if (!dgclass->initialized)
12551                 return TRUE;
12552
12553         if (klass->method.count != gklass->method.count) {
12554                 klass->method.count = gklass->method.count;
12555                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12556
12557                 for (i = 0; i < klass->method.count; i++) {
12558                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12559                                 gklass->methods [i], klass, mono_class_get_context (klass), error);
12560                         mono_error_assert_ok (error);
12561                 }
12562         }
12563
12564         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12565                 klass->interface_count = gklass->interface_count;
12566                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12567                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12568
12569                 for (i = 0; i < gklass->interface_count; ++i) {
12570                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12571                         return_val_if_nok (error, FALSE);
12572
12573                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12574                         mono_metadata_free_type (iface_type);
12575
12576                         if (!ensure_runtime_vtable (klass->interfaces [i], error))
12577                                 return FALSE;
12578                 }
12579                 klass->interfaces_inited = 1;
12580         }
12581
12582         if (klass->field.count != gklass->field.count) {
12583                 klass->field.count = gklass->field.count;
12584                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12585
12586                 for (i = 0; i < klass->field.count; i++) {
12587                         klass->fields [i] = gklass->fields [i];
12588                         klass->fields [i].parent = klass;
12589                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12590                         return_val_if_nok (error, FALSE);
12591                 }
12592         }
12593
12594         /*We can only finish with this klass once it's parent has as well*/
12595         if (gklass->wastypebuilder)
12596                 klass->wastypebuilder = TRUE;
12597         return TRUE;
12598 }
12599
12600 /**
12601  * ensure_generic_class_runtime_vtable:
12602  * @klass a generic class
12603  * @error set on error
12604  *
12605  * Ensures that the generic container of @klass has a vtable and
12606  * returns TRUE on success.  On error returns FALSE and sets @error.
12607  */
12608 static gboolean
12609 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12610 {
12611         MonoClass *gklass = klass->generic_class->container_class;
12612
12613         mono_error_init (error);
12614
12615         if (!ensure_runtime_vtable (gklass, error))
12616                 return FALSE;
12617
12618         return fix_partial_generic_class (klass, error);
12619 }
12620
12621 /**
12622  * ensure_runtime_vtable:
12623  * @klass the class
12624  * @error set on error
12625  *
12626  * Ensures that @klass has a vtable and returns TRUE on success. On
12627  * error returns FALSE and sets @error.
12628  */
12629 static gboolean
12630 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12631 {
12632         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12633         int i, num, j;
12634
12635         mono_error_init (error);
12636
12637         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12638                 return TRUE;
12639         if (klass->parent)
12640                 if (!ensure_runtime_vtable (klass->parent, error))
12641                         return FALSE;
12642
12643         if (tb) {
12644                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12645                 num += tb->num_methods;
12646                 klass->method.count = num;
12647                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12648                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12649                 for (i = 0; i < num; ++i) {
12650                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12651                         if (!ctor)
12652                                 return FALSE;
12653                         klass->methods [i] = ctor;
12654                 }
12655                 num = tb->num_methods;
12656                 j = i;
12657                 for (i = 0; i < num; ++i) {
12658                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12659                         if (!meth)
12660                                 return FALSE;
12661                         klass->methods [j++] = meth;
12662                 }
12663         
12664                 if (tb->interfaces) {
12665                         klass->interface_count = mono_array_length (tb->interfaces);
12666                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12667                         for (i = 0; i < klass->interface_count; ++i) {
12668                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12669                                 return_val_if_nok (error, FALSE);
12670                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12671                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12672                                         return FALSE;
12673                         }
12674                         klass->interfaces_inited = 1;
12675                 }
12676         } else if (klass->generic_class){
12677                 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12678                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12679                         return FALSE;
12680                 }
12681         }
12682
12683         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12684                 int slot_num = 0;
12685                 for (i = 0; i < klass->method.count; ++i) {
12686                         MonoMethod *im = klass->methods [i];
12687                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12688                                 im->slot = slot_num++;
12689                 }
12690                 
12691                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12692                 mono_class_setup_interface_offsets (klass);
12693                 mono_class_setup_interface_id (klass);
12694         }
12695
12696         /*
12697          * The generic vtable is needed even if image->run is not set since some
12698          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12699          * method->slot being defined.
12700          */
12701
12702         /* 
12703          * tb->methods could not be freed since it is used for determining 
12704          * overrides during dynamic vtable construction.
12705          */
12706
12707         return TRUE;
12708 }
12709
12710 static MonoMethod*
12711 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12712 {
12713         mono_error_init (error);
12714         MonoClass *klass = mono_object_class (method);
12715         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12716                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12717                 return sr_method->method;
12718         }
12719         if (is_sre_method_builder (klass)) {
12720                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12721                 return mb->mhandle;
12722         }
12723         if (is_sre_method_on_tb_inst (klass)) {
12724                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12725                 MonoMethod *result;
12726                 /*FIXME move this to a proper method and unify with resolve_object*/
12727                 if (m->method_args) {
12728                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12729                 } else {
12730                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12731                         return_val_if_nok (error, NULL);
12732                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12733                         MonoMethod *mono_method;
12734
12735                         if (is_sre_method_builder (mono_object_class (m->mb)))
12736                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12737                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12738                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12739                         else
12740                                 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)));
12741
12742                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12743                 }
12744                 return result;
12745         }
12746
12747         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12748         return NULL;
12749 }
12750
12751 void
12752 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12753 {
12754         MonoReflectionTypeBuilder *tb;
12755         int i, j, onum;
12756         MonoReflectionMethod *m;
12757
12758         mono_error_init (error);
12759         *overrides = NULL;
12760         *num_overrides = 0;
12761
12762         g_assert (image_is_dynamic (klass->image));
12763
12764         if (!mono_class_get_ref_info (klass))
12765                 return;
12766
12767         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12768
12769         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12770
12771         onum = 0;
12772         if (tb->methods) {
12773                 for (i = 0; i < tb->num_methods; ++i) {
12774                         MonoReflectionMethodBuilder *mb = 
12775                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12776                         if (mb->override_methods)
12777                                 onum += mono_array_length (mb->override_methods);
12778                 }
12779         }
12780
12781         if (onum) {
12782                 *overrides = g_new0 (MonoMethod*, onum * 2);
12783
12784                 onum = 0;
12785                 for (i = 0; i < tb->num_methods; ++i) {
12786                         MonoReflectionMethodBuilder *mb = 
12787                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12788                         if (mb->override_methods) {
12789                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12790                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12791
12792                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12793                                         return_if_nok (error);
12794                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12795
12796                                         g_assert (mb->mhandle);
12797
12798                                         onum ++;
12799                                 }
12800                         }
12801                 }
12802         }
12803
12804         *num_overrides = onum;
12805 }
12806
12807 static void
12808 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12809 {
12810         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12811         MonoReflectionFieldBuilder *fb;
12812         MonoClassField *field;
12813         MonoImage *image = klass->image;
12814         const char *p, *p2;
12815         int i;
12816         guint32 len, idx, real_size = 0;
12817
12818         klass->field.count = tb->num_fields;
12819         klass->field.first = 0;
12820
12821         mono_error_init (error);
12822
12823         if (tb->class_size) {
12824                 if ((tb->packing_size & 0xffffff00) != 0) {
12825                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12826                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12827                         return;
12828                 }
12829                 klass->packing_size = tb->packing_size;
12830                 real_size = klass->instance_size + tb->class_size;
12831         }
12832
12833         if (!klass->field.count) {
12834                 klass->instance_size = MAX (klass->instance_size, real_size);
12835                 return;
12836         }
12837         
12838         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12839         mono_class_alloc_ext (klass);
12840         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12841         /*
12842         This is, guess what, a hack.
12843         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12844         On the static path no field class is resolved, only types are built. This is the right thing to do
12845         but we suck.
12846         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12847         */
12848         klass->size_inited = 1;
12849
12850         for (i = 0; i < klass->field.count; ++i) {
12851                 MonoArray *rva_data;
12852                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12853                 field = &klass->fields [i];
12854                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12855                 if (!mono_error_ok (error))
12856                         return;
12857                 if (fb->attrs) {
12858                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12859                         return_if_nok (error);
12860                         field->type = mono_metadata_type_dup (klass->image, type);
12861                         field->type->attrs = fb->attrs;
12862                 } else {
12863                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12864                         return_if_nok (error);
12865                 }
12866
12867                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12868                         char *base = mono_array_addr (rva_data, char, 0);
12869                         size_t size = mono_array_length (rva_data);
12870                         char *data = (char *)mono_image_alloc (klass->image, size);
12871                         memcpy (data, base, size);
12872                         klass->ext->field_def_values [i].data = data;
12873                 }
12874                 if (fb->offset != -1)
12875                         field->offset = fb->offset;
12876                 field->parent = klass;
12877                 fb->handle = field;
12878                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12879
12880                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12881                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12882                 }
12883                 if (fb->def_value) {
12884                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12885                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12886                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12887                         /* Copy the data from the blob since it might get realloc-ed */
12888                         p = assembly->blob.data + idx;
12889                         len = mono_metadata_decode_blob_size (p, &p2);
12890                         len += p2 - p;
12891                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12892                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12893                 }
12894         }
12895
12896         klass->instance_size = MAX (klass->instance_size, real_size);
12897         mono_class_layout_fields (klass);
12898 }
12899
12900 static void
12901 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12902 {
12903         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12904         MonoReflectionPropertyBuilder *pb;
12905         MonoImage *image = klass->image;
12906         MonoProperty *properties;
12907         int i;
12908
12909         mono_error_init (error);
12910
12911         if (!klass->ext)
12912                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12913
12914         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12915         klass->ext->property.first = 0;
12916
12917         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12918         klass->ext->properties = properties;
12919         for (i = 0; i < klass->ext->property.count; ++i) {
12920                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12921                 properties [i].parent = klass;
12922                 properties [i].attrs = pb->attrs;
12923                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12924                 if (!mono_error_ok (error))
12925                         return;
12926                 if (pb->get_method)
12927                         properties [i].get = pb->get_method->mhandle;
12928                 if (pb->set_method)
12929                         properties [i].set = pb->set_method->mhandle;
12930
12931                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12932                 if (pb->def_value) {
12933                         guint32 len, idx;
12934                         const char *p, *p2;
12935                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12936                         if (!klass->ext->prop_def_values)
12937                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12938                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12939                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12940                         /* Copy the data from the blob since it might get realloc-ed */
12941                         p = assembly->blob.data + idx;
12942                         len = mono_metadata_decode_blob_size (p, &p2);
12943                         len += p2 - p;
12944                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12945                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12946                 }
12947         }
12948 }
12949
12950 static MonoReflectionEvent *
12951 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
12952 {
12953         mono_error_init (error);
12954
12955         MonoEvent *event = g_new0 (MonoEvent, 1);
12956         MonoClass *klass;
12957
12958         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
12959         if (!is_ok (error)) {
12960                 g_free (event);
12961                 return NULL;
12962         }
12963         klass = mono_class_from_mono_type (type);
12964
12965         event->parent = klass;
12966         event->attrs = eb->attrs;
12967         event->name = mono_string_to_utf8 (eb->name);
12968         if (eb->add_method)
12969                 event->add = eb->add_method->mhandle;
12970         if (eb->remove_method)
12971                 event->remove = eb->remove_method->mhandle;
12972         if (eb->raise_method)
12973                 event->raise = eb->raise_method->mhandle;
12974
12975 #ifndef MONO_SMALL_CONFIG
12976         if (eb->other_methods) {
12977                 int j;
12978                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12979                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12980                         MonoReflectionMethodBuilder *mb = 
12981                                 mono_array_get (eb->other_methods,
12982                                                 MonoReflectionMethodBuilder*, j);
12983                         event->other [j] = mb->mhandle;
12984                 }
12985         }
12986 #endif
12987
12988         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
12989         if (!is_ok (error)) {
12990 #ifndef MONO_SMALL_CONFIG
12991                 g_free (event->other);
12992 #endif
12993                 g_free (event);
12994                 return NULL;
12995         }
12996         return ev_obj;
12997 }
12998
12999 MonoReflectionEvent *
13000 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13001 {
13002         MonoError error;
13003         MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13004         mono_error_set_pending_exception (&error);
13005         return result;
13006 }
13007
13008 static void
13009 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13010 {
13011         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13012         MonoReflectionEventBuilder *eb;
13013         MonoImage *image = klass->image;
13014         MonoEvent *events;
13015         int i;
13016
13017         mono_error_init (error);
13018
13019         if (!klass->ext)
13020                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13021
13022         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13023         klass->ext->event.first = 0;
13024
13025         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13026         klass->ext->events = events;
13027         for (i = 0; i < klass->ext->event.count; ++i) {
13028                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13029                 events [i].parent = klass;
13030                 events [i].attrs = eb->attrs;
13031                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13032                 if (!mono_error_ok (error))
13033                         return;
13034                 if (eb->add_method)
13035                         events [i].add = eb->add_method->mhandle;
13036                 if (eb->remove_method)
13037                         events [i].remove = eb->remove_method->mhandle;
13038                 if (eb->raise_method)
13039                         events [i].raise = eb->raise_method->mhandle;
13040
13041 #ifndef MONO_SMALL_CONFIG
13042                 if (eb->other_methods) {
13043                         int j;
13044                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13045                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13046                                 MonoReflectionMethodBuilder *mb = 
13047                                         mono_array_get (eb->other_methods,
13048                                                                         MonoReflectionMethodBuilder*, j);
13049                                 events [i].other [j] = mb->mhandle;
13050                         }
13051                 }
13052 #endif
13053                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13054         }
13055 }
13056
13057 struct remove_instantiations_user_data
13058 {
13059         MonoClass *klass;
13060         MonoError *error;
13061 };
13062
13063 static gboolean
13064 remove_instantiations_of_and_ensure_contents (gpointer key,
13065                                                   gpointer value,
13066                                                   gpointer user_data)
13067 {
13068         struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13069         MonoType *type = (MonoType*)key;
13070         MonoClass *klass = data->klass;
13071         gboolean already_failed = !is_ok (data->error);
13072         MonoError lerror;
13073         MonoError *error = already_failed ? &lerror : data->error;
13074
13075         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13076                 MonoClass *inst_klass = mono_class_from_mono_type (type);
13077                 //Ensure it's safe to use it.
13078                 if (!fix_partial_generic_class (inst_klass, error)) {
13079                         mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13080                         // Marked the class with failure, but since some other instantiation already failed,
13081                         // just report that one, and swallow the error from this one.
13082                         if (already_failed)
13083                                 mono_error_cleanup (error);
13084                 }
13085                 return TRUE;
13086         } else
13087                 return FALSE;
13088 }
13089
13090 static void
13091 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13092 {
13093         mono_error_init (error);
13094         int i;
13095
13096         if (!arr)
13097                 return;
13098
13099         for (i = 0; i < mono_array_length (arr); ++i) {
13100                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13101                 if (!mono_error_ok (error))
13102                         break;
13103         }
13104 }
13105
13106 MonoReflectionType*
13107 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13108 {
13109         MonoError error;
13110         MonoClass *klass;
13111         MonoDomain* domain;
13112         MonoReflectionType* res;
13113         int i, j;
13114
13115         mono_error_init (&error);
13116
13117         domain = mono_object_domain (tb);
13118         klass = mono_class_from_mono_type (tb->type.type);
13119
13120         /*
13121          * Check for user defined Type subclasses.
13122          */
13123         RESOLVE_TYPE (tb->parent, &error);
13124         if (!is_ok (&error))
13125                 goto failure_unlocked;
13126         check_array_for_usertypes (tb->interfaces, &error);
13127         if (!is_ok (&error))
13128                 goto failure_unlocked;
13129         if (tb->fields) {
13130                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13131                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13132                         if (fb) {
13133                                 RESOLVE_TYPE (fb->type, &error);
13134                                 if (!is_ok (&error))
13135                                         goto failure_unlocked;
13136                                 check_array_for_usertypes (fb->modreq, &error);
13137                                 if (!is_ok (&error))
13138                                         goto failure_unlocked;
13139                                 check_array_for_usertypes (fb->modopt, &error);
13140                                 if (!is_ok (&error))
13141                                         goto failure_unlocked;
13142                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13143                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13144                                         if (!is_ok (&error))
13145                                                 goto failure_unlocked;
13146                                 }
13147                         }
13148                 }
13149         }
13150         if (tb->methods) {
13151                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13152                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13153                         if (mb) {
13154                                 RESOLVE_TYPE (mb->rtype, &error);
13155                                 if (!is_ok (&error))
13156                                         goto failure_unlocked;
13157                                 check_array_for_usertypes (mb->return_modreq, &error);
13158                                 if (!is_ok (&error))
13159                                         goto failure_unlocked;
13160                                 check_array_for_usertypes (mb->return_modopt, &error);
13161                                 if (!is_ok (&error))
13162                                         goto failure_unlocked;
13163                                 check_array_for_usertypes (mb->parameters, &error);
13164                                 if (!is_ok (&error))
13165                                         goto failure_unlocked;
13166                                 if (mb->param_modreq)
13167                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13168                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13169                                                 if (!is_ok (&error))
13170                                                         goto failure_unlocked;
13171                                         }
13172                                 if (mb->param_modopt)
13173                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13174                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13175                                                 if (!is_ok (&error))
13176                                                         goto failure_unlocked;
13177                                         }
13178                         }
13179                 }
13180         }
13181         if (tb->ctors) {
13182                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13183                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13184                         if (mb) {
13185                                 check_array_for_usertypes (mb->parameters, &error);
13186                                 if (!is_ok (&error))
13187                                         goto failure_unlocked;
13188                                 if (mb->param_modreq)
13189                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13190                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13191                                                 if (!is_ok (&error))
13192                                                         goto failure_unlocked;
13193                                         }
13194                                 if (mb->param_modopt)
13195                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13196                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13197                                                 if (!is_ok (&error))
13198                                                         goto failure_unlocked;
13199                                         }
13200                         }
13201                 }
13202         }
13203
13204         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13205
13206         /* 
13207          * we need to lock the domain because the lock will be taken inside
13208          * So, we need to keep the locking order correct.
13209          */
13210         mono_loader_lock ();
13211         mono_domain_lock (domain);
13212         if (klass->wastypebuilder) {
13213                 mono_domain_unlock (domain);
13214                 mono_loader_unlock ();
13215
13216                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13217                 mono_error_set_pending_exception (&error);
13218
13219                 return res;
13220         }
13221         /*
13222          * Fields to set in klass:
13223          * the various flags: delegate/unicode/contextbound etc.
13224          */
13225         klass->flags = tb->attrs;
13226         klass->has_cctor = 1;
13227         klass->has_finalize = 1;
13228         klass->has_finalize_inited = 1;
13229
13230         mono_class_setup_parent (klass, klass->parent);
13231         /* fool mono_class_setup_supertypes */
13232         klass->supertypes = NULL;
13233         mono_class_setup_supertypes (klass);
13234         mono_class_setup_mono_type (klass);
13235
13236 #if 0
13237         if (!((MonoDynamicImage*)klass->image)->run) {
13238                 if (klass->generic_container) {
13239                         /* FIXME: The code below can't handle generic classes */
13240                         klass->wastypebuilder = TRUE;
13241                         mono_loader_unlock ();
13242                         mono_domain_unlock (domain);
13243
13244                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13245                         mono_error_set_pending_exception (&error);
13246
13247                         return res;
13248                 }
13249         }
13250 #endif
13251
13252         /* enums are done right away */
13253         if (!klass->enumtype)
13254                 if (!ensure_runtime_vtable (klass, &error))
13255                         goto failure;
13256
13257         if (tb->subtypes) {
13258                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13259                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13260                         mono_class_alloc_ext (klass);
13261                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13262                         if (!is_ok (&error)) goto failure;
13263                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13264                 }
13265         }
13266
13267         klass->nested_classes_inited = TRUE;
13268
13269         /* fields and object layout */
13270         if (klass->parent) {
13271                 if (!klass->parent->size_inited)
13272                         mono_class_init (klass->parent);
13273                 klass->instance_size = klass->parent->instance_size;
13274                 klass->sizes.class_size = 0;
13275                 klass->min_align = klass->parent->min_align;
13276                 /* if the type has no fields we won't call the field_setup
13277                  * routine which sets up klass->has_references.
13278                  */
13279                 klass->has_references |= klass->parent->has_references;
13280         } else {
13281                 klass->instance_size = sizeof (MonoObject);
13282                 klass->min_align = 1;
13283         }
13284
13285         /* FIXME: handle packing_size and instance_size */
13286         typebuilder_setup_fields (klass, &error);
13287         if (!mono_error_ok (&error))
13288                 goto failure;
13289         typebuilder_setup_properties (klass, &error);
13290         if (!mono_error_ok (&error))
13291                 goto failure;
13292
13293         typebuilder_setup_events (klass, &error);
13294         if (!mono_error_ok (&error))
13295                 goto failure;
13296
13297         klass->wastypebuilder = TRUE;
13298
13299         /* 
13300          * If we are a generic TypeBuilder, there might be instantiations in the type cache
13301          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
13302          * we want to return normal System.MonoType objects, so clear these out from the cache.
13303          *
13304          * Together with this we must ensure the contents of all instances to match the created type.
13305          */
13306         if (domain->type_hash && klass->generic_container) {
13307                 struct remove_instantiations_user_data data;
13308                 data.klass = klass;
13309                 data.error = &error;
13310                 mono_error_assert_ok (&error);
13311                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13312                 if (!is_ok (&error))
13313                         goto failure;
13314         }
13315
13316         mono_domain_unlock (domain);
13317         mono_loader_unlock ();
13318
13319         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13320                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13321                 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13322                 goto failure_unlocked;
13323         }
13324
13325         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13326         if (!is_ok (&error))
13327                 goto failure_unlocked;
13328
13329         g_assert (res != (MonoReflectionType*)tb);
13330
13331         return res;
13332
13333 failure:
13334         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13335         klass->wastypebuilder = TRUE;
13336         mono_domain_unlock (domain);
13337         mono_loader_unlock ();
13338 failure_unlocked:
13339         mono_error_set_pending_exception (&error);
13340         return NULL;
13341 }
13342
13343 static gboolean
13344 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13345 {
13346         MonoGenericParamFull *param;
13347         MonoImage *image;
13348         MonoClass *pklass;
13349
13350         mono_error_init (error);
13351
13352         image = &gparam->tbuilder->module->dynamic_image->image;
13353
13354         param = mono_image_new0 (image, MonoGenericParamFull, 1);
13355
13356         param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13357         mono_error_assert_ok (error);
13358         param->param.num = gparam->index;
13359
13360         if (gparam->mbuilder) {
13361                 if (!gparam->mbuilder->generic_container) {
13362                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13363                         return_val_if_nok (error, FALSE);
13364
13365                         MonoClass *klass = mono_class_from_mono_type (tb);
13366                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13367                         gparam->mbuilder->generic_container->is_method = TRUE;
13368                         /* 
13369                          * Cannot set owner.method, since the MonoMethod is not created yet.
13370                          * Set the image field instead, so type_in_image () works.
13371                          */
13372                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
13373                         gparam->mbuilder->generic_container->owner.image = klass->image;
13374                 }
13375                 param->param.owner = gparam->mbuilder->generic_container;
13376         } else if (gparam->tbuilder) {
13377                 if (!gparam->tbuilder->generic_container) {
13378                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13379                         return_val_if_nok (error, FALSE);
13380                         MonoClass *klass = mono_class_from_mono_type (tb);
13381                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13382                         gparam->tbuilder->generic_container->owner.klass = klass;
13383                 }
13384                 param->param.owner = gparam->tbuilder->generic_container;
13385         }
13386
13387         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13388
13389         gparam->type.type = &pklass->byval_arg;
13390
13391         mono_class_set_ref_info (pklass, gparam);
13392         mono_image_append_class_to_reflection_info_set (pklass);
13393
13394         return TRUE;
13395 }
13396
13397 void
13398 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13399 {
13400         MonoError error;
13401         (void) reflection_initialize_generic_parameter (gparam, &error);
13402         mono_error_set_pending_exception (&error);
13403 }
13404
13405
13406 MonoArray *
13407 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13408 {
13409         MonoError error;
13410         MonoReflectionModuleBuilder *module = sig->module;
13411         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13412         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13413         guint32 buflen, i;
13414         MonoArray *result;
13415         SigBuffer buf;
13416
13417         check_array_for_usertypes (sig->arguments, &error);
13418         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13419
13420         sigbuffer_init (&buf, 32);
13421
13422         sigbuffer_add_value (&buf, 0x07);
13423         sigbuffer_add_value (&buf, na);
13424         if (assembly != NULL){
13425                 for (i = 0; i < na; ++i) {
13426                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13427                         encode_reflection_type (assembly, type, &buf, &error);
13428                         if (!is_ok (&error)) goto fail;
13429                 }
13430         }
13431
13432         buflen = buf.p - buf.buf;
13433         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13434         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13435         sigbuffer_free (&buf);
13436         return result;
13437 fail:
13438         sigbuffer_free (&buf);
13439         mono_error_raise_exception (&error); /* FIXME don't raise here */
13440         return NULL;
13441 }
13442
13443 MonoArray *
13444 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13445 {
13446         MonoError error;
13447         MonoDynamicImage *assembly = sig->module->dynamic_image;
13448         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13449         guint32 buflen, i;
13450         MonoArray *result;
13451         SigBuffer buf;
13452
13453         check_array_for_usertypes (sig->arguments, &error);
13454         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13455
13456         sigbuffer_init (&buf, 32);
13457
13458         sigbuffer_add_value (&buf, 0x06);
13459         for (i = 0; i < na; ++i) {
13460                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13461                 encode_reflection_type (assembly, type, &buf, &error);
13462                 if (!is_ok (&error))
13463                         goto fail;
13464         }
13465
13466         buflen = buf.p - buf.buf;
13467         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13468         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13469         sigbuffer_free (&buf);
13470
13471         return result;
13472 fail:
13473         sigbuffer_free (&buf);
13474         mono_error_raise_exception (&error); /* FIXME don't raise here */
13475         return NULL;
13476 }
13477
13478 typedef struct {
13479         MonoMethod *handle;
13480         MonoDomain *domain;
13481 } DynamicMethodReleaseData;
13482
13483 /*
13484  * The runtime automatically clean up those after finalization.
13485 */      
13486 static MonoReferenceQueue *dynamic_method_queue;
13487
13488 static void
13489 free_dynamic_method (void *dynamic_method)
13490 {
13491         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13492         MonoDomain *domain = data->domain;
13493         MonoMethod *method = data->handle;
13494         guint32 dis_link;
13495
13496         mono_domain_lock (domain);
13497         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13498         g_hash_table_remove (domain->method_to_dyn_method, method);
13499         mono_domain_unlock (domain);
13500         g_assert (dis_link);
13501         mono_gchandle_free (dis_link);
13502
13503         mono_runtime_free_method (domain, method);
13504         g_free (data);
13505 }
13506
13507 static gboolean
13508 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13509 {
13510         MonoReferenceQueue *queue;
13511         MonoMethod *handle;
13512         DynamicMethodReleaseData *release_data;
13513         ReflectionMethodBuilder rmb;
13514         MonoMethodSignature *sig;
13515         MonoClass *klass;
13516         MonoDomain *domain;
13517         GSList *l;
13518         int i;
13519
13520         mono_error_init (error);
13521
13522         if (mono_runtime_is_shutting_down ()) {
13523                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13524                 return FALSE;
13525         }
13526
13527         if (!(queue = dynamic_method_queue)) {
13528                 mono_loader_lock ();
13529                 if (!(queue = dynamic_method_queue))
13530                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13531                 mono_loader_unlock ();
13532         }
13533
13534         sig = dynamic_method_to_signature (mb, error);
13535         return_val_if_nok (error, FALSE);
13536
13537         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13538
13539         /*
13540          * Resolve references.
13541          */
13542         /* 
13543          * Every second entry in the refs array is reserved for storing handle_class,
13544          * which is needed by the ldtoken implementation in the JIT.
13545          */
13546         rmb.nrefs = mb->nrefs;
13547         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13548         for (i = 0; i < mb->nrefs; i += 2) {
13549                 MonoClass *handle_class;
13550                 gpointer ref;
13551                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13552
13553                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13554                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13555                         /*
13556                          * The referenced DynamicMethod should already be created by the managed
13557                          * code, except in the case of circular references. In that case, we store
13558                          * method in the refs array, and fix it up later when the referenced 
13559                          * DynamicMethod is created.
13560                          */
13561                         if (method->mhandle) {
13562                                 ref = method->mhandle;
13563                         } else {
13564                                 /* FIXME: GC object stored in unmanaged memory */
13565                                 ref = method;
13566
13567                                 /* FIXME: GC object stored in unmanaged memory */
13568                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13569                         }
13570                         handle_class = mono_defaults.methodhandle_class;
13571                 } else {
13572                         MonoException *ex = NULL;
13573                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13574                         if (!is_ok  (error)) {
13575                                 g_free (rmb.refs);
13576                                 return FALSE;
13577                         }
13578                         if (!ref)
13579                                 ex = mono_get_exception_type_load (NULL, NULL);
13580                         else if (mono_security_core_clr_enabled ())
13581                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13582
13583                         if (ex) {
13584                                 g_free (rmb.refs);
13585                                 mono_error_set_exception_instance (error, ex);
13586                                 return FALSE;
13587                         }
13588                 }
13589
13590                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13591                 rmb.refs [i + 1] = handle_class;
13592         }               
13593
13594         if (mb->owner) {
13595                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13596                 if (!is_ok (error)) {
13597                         g_free (rmb.refs);
13598                         return FALSE;
13599                 }
13600                 klass = mono_class_from_mono_type (owner_type);
13601         } else {
13602                 klass = mono_defaults.object_class;
13603         }
13604
13605         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13606         release_data = g_new (DynamicMethodReleaseData, 1);
13607         release_data->handle = handle;
13608         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13609         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13610                 g_free (release_data);
13611
13612         /* Fix up refs entries pointing at us */
13613         for (l = mb->referenced_by; l; l = l->next) {
13614                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13615                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13616                 gpointer *data;
13617                 
13618                 g_assert (method->mhandle);
13619
13620                 data = (gpointer*)wrapper->method_data;
13621                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13622                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13623                                 data [i + 1] = mb->mhandle;
13624                 }
13625         }
13626         g_slist_free (mb->referenced_by);
13627
13628         g_free (rmb.refs);
13629
13630         /* ilgen is no longer needed */
13631         mb->ilgen = NULL;
13632
13633         domain = mono_domain_get ();
13634         mono_domain_lock (domain);
13635         if (!domain->method_to_dyn_method)
13636                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13637         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13638         mono_domain_unlock (domain);
13639
13640         return TRUE;
13641 }
13642
13643 void
13644 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13645 {
13646         MonoError error;
13647         (void) reflection_create_dynamic_method (mb, &error);
13648         mono_error_set_pending_exception (&error);
13649 }
13650
13651 #endif /* DISABLE_REFLECTION_EMIT */
13652
13653 /**
13654  * 
13655  * mono_reflection_is_valid_dynamic_token:
13656  * 
13657  * Returns TRUE if token is valid.
13658  * 
13659  */
13660 gboolean
13661 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13662 {
13663         return lookup_dyn_token (image, token) != NULL;
13664 }
13665
13666 MonoMethodSignature *
13667 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13668 {
13669         MonoMethodSignature *sig;
13670         g_assert (image_is_dynamic (image));
13671
13672         mono_error_init (error);
13673
13674         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13675         if (sig)
13676                 return sig;
13677
13678         return mono_method_signature_checked (method, error);
13679 }
13680
13681 #ifndef DISABLE_REFLECTION_EMIT
13682
13683 /**
13684  * mono_reflection_lookup_dynamic_token:
13685  *
13686  * Finish the Builder object pointed to by TOKEN and return the corresponding
13687  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13688  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13689  * mapping table.
13690  *
13691  * LOCKING: Take the loader lock
13692  */
13693 gpointer
13694 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13695 {
13696         MonoError error;
13697         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13698         MonoObject *obj;
13699         MonoClass *klass;
13700
13701         obj = lookup_dyn_token (assembly, token);
13702         if (!obj) {
13703                 if (valid_token)
13704                         g_error ("Could not find required dynamic token 0x%08x", token);
13705                 else
13706                         return NULL;
13707         }
13708
13709         if (!handle_class)
13710                 handle_class = &klass;
13711         gpointer result = resolve_object (image, obj, handle_class, context, &error);
13712         mono_error_raise_exception (&error); /* FIXME don't raise here */
13713         return result;
13714 }
13715
13716 /*
13717  * ensure_complete_type:
13718  *
13719  *   Ensure that KLASS is completed if it is a dynamic type, or references
13720  * dynamic types.
13721  */
13722 static void
13723 ensure_complete_type (MonoClass *klass, MonoError *error)
13724 {
13725         mono_error_init (error);
13726
13727         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13728                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13729
13730                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13731                 return_if_nok (error);
13732
13733                 // Asserting here could break a lot of code
13734                 //g_assert (klass->wastypebuilder);
13735         }
13736
13737         if (klass->generic_class) {
13738                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13739                 int i;
13740
13741                 for (i = 0; i < inst->type_argc; ++i) {
13742                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13743                         return_if_nok (error);
13744                 }
13745         }
13746 }
13747
13748 static gpointer
13749 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13750 {
13751         gpointer result = NULL;
13752
13753         mono_error_init (error);
13754
13755         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13756                 result = mono_string_intern_checked ((MonoString*)obj, error);
13757                 return_val_if_nok (error, NULL);
13758                 *handle_class = mono_defaults.string_class;
13759                 g_assert (result);
13760         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13761                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13762                 return_val_if_nok (error, NULL);
13763                 MonoClass *mc = mono_class_from_mono_type (type);
13764                 if (!mono_class_init (mc)) {
13765                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13766                         return NULL;
13767                 }
13768
13769                 if (context) {
13770                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13771                         return_val_if_nok (error, NULL);
13772
13773                         result = mono_class_from_mono_type (inflated);
13774                         mono_metadata_free_type (inflated);
13775                 } else {
13776                         result = mono_class_from_mono_type (type);
13777                 }
13778                 *handle_class = mono_defaults.typehandle_class;
13779                 g_assert (result);
13780         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13781                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13782                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13783                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13784                 result = ((MonoReflectionMethod*)obj)->method;
13785                 if (context) {
13786                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13787                         mono_error_assert_ok (error);
13788                 }
13789                 *handle_class = mono_defaults.methodhandle_class;
13790                 g_assert (result);
13791         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13792                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13793                 result = mb->mhandle;
13794                 if (!result) {
13795                         /* Type is not yet created */
13796                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13797
13798                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13799                         return_val_if_nok (error, NULL);
13800
13801                         /*
13802                          * Hopefully this has been filled in by calling CreateType() on the
13803                          * TypeBuilder.
13804                          */
13805                         /*
13806                          * TODO: This won't work if the application finishes another 
13807                          * TypeBuilder instance instead of this one.
13808                          */
13809                         result = mb->mhandle;
13810                 }
13811                 if (context) {
13812                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13813                         mono_error_assert_ok (error);
13814                 }
13815                 *handle_class = mono_defaults.methodhandle_class;
13816         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13817                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13818
13819                 result = cb->mhandle;
13820                 if (!result) {
13821                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13822
13823                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13824                         return_val_if_nok (error, NULL);
13825                         result = cb->mhandle;
13826                 }
13827                 if (context) {
13828                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13829                         mono_error_assert_ok (error);
13830                 }
13831                 *handle_class = mono_defaults.methodhandle_class;
13832         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13833                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13834
13835                 ensure_complete_type (field->parent, error);
13836                 return_val_if_nok (error, NULL);
13837
13838                 if (context) {
13839                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13840                         return_val_if_nok (error, NULL);
13841
13842                         MonoClass *klass = mono_class_from_mono_type (inflated);
13843                         MonoClassField *inflated_field;
13844                         gpointer iter = NULL;
13845                         mono_metadata_free_type (inflated);
13846                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13847                                 if (!strcmp (field->name, inflated_field->name))
13848                                         break;
13849                         }
13850                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13851                         result = inflated_field;
13852                 } else {
13853                         result = field;
13854                 }
13855                 *handle_class = mono_defaults.fieldhandle_class;
13856                 g_assert (result);
13857         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13858                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13859                 result = fb->handle;
13860
13861                 if (!result) {
13862                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13863
13864                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13865                         return_val_if_nok (error, NULL);
13866                         result = fb->handle;
13867                 }
13868
13869                 if (fb->handle && fb->handle->parent->generic_container) {
13870                         MonoClass *klass = fb->handle->parent;
13871                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
13872                         return_val_if_nok (error, NULL);
13873
13874                         MonoClass *inflated = mono_class_from_mono_type (type);
13875
13876                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13877                         g_assert (result);
13878                         mono_metadata_free_type (type);
13879                 }
13880                 *handle_class = mono_defaults.fieldhandle_class;
13881         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13882                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13883                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13884                 return_val_if_nok (error, NULL);
13885                 MonoClass *klass;
13886
13887                 klass = type->data.klass;
13888                 if (klass->wastypebuilder) {
13889                         /* Already created */
13890                         result = klass;
13891                 }
13892                 else {
13893                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13894                         return_val_if_nok (error, NULL);
13895                         result = type->data.klass;
13896                         g_assert (result);
13897                 }
13898                 *handle_class = mono_defaults.typehandle_class;
13899         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13900                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13901                 MonoMethodSignature *sig;
13902                 int nargs, i;
13903
13904                 if (helper->arguments)
13905                         nargs = mono_array_length (helper->arguments);
13906                 else
13907                         nargs = 0;
13908
13909                 sig = mono_metadata_signature_alloc (image, nargs);
13910                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13911                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13912
13913                 if (helper->unmanaged_call_conv) { /* unmanaged */
13914                         sig->call_convention = helper->unmanaged_call_conv - 1;
13915                         sig->pinvoke = TRUE;
13916                 } else if (helper->call_conv & 0x02) {
13917                         sig->call_convention = MONO_CALL_VARARG;
13918                 } else {
13919                         sig->call_convention = MONO_CALL_DEFAULT;
13920                 }
13921
13922                 sig->param_count = nargs;
13923                 /* TODO: Copy type ? */
13924                 sig->ret = helper->return_type->type;
13925                 for (i = 0; i < nargs; ++i) {
13926                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
13927                         if (!is_ok (error)) {
13928                                 image_g_free (image, sig);
13929                                 return NULL;
13930                         }
13931                 }
13932
13933                 result = sig;
13934                 *handle_class = NULL;
13935         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13936                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13937                 /* Already created by the managed code */
13938                 g_assert (method->mhandle);
13939                 result = method->mhandle;
13940                 *handle_class = mono_defaults.methodhandle_class;
13941         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13942                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13943                 return_val_if_nok (error, NULL);
13944                 type = mono_class_inflate_generic_type_checked (type, context, error);
13945                 return_val_if_nok (error, NULL);
13946
13947                 result = mono_class_from_mono_type (type);
13948                 *handle_class = mono_defaults.typehandle_class;
13949                 g_assert (result);
13950                 mono_metadata_free_type (type);
13951         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13952                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13953                 return_val_if_nok (error, NULL);
13954                 type = mono_class_inflate_generic_type_checked (type, context, error);
13955                 return_val_if_nok (error, NULL);
13956
13957                 result = mono_class_from_mono_type (type);
13958                 *handle_class = mono_defaults.typehandle_class;
13959                 g_assert (result);
13960                 mono_metadata_free_type (type);
13961         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13962                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13963                 MonoClass *inflated;
13964                 MonoType *type;
13965                 MonoClassField *field;
13966
13967                 if (is_sre_field_builder (mono_object_class (f->fb)))
13968                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13969                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13970                         field = ((MonoReflectionField*)f->fb)->field;
13971                 else
13972                         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)));
13973
13974                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
13975                 return_val_if_nok (error, NULL);
13976                 type = mono_class_inflate_generic_type_checked (finst, context, error);
13977                 return_val_if_nok (error, NULL);
13978
13979                 inflated = mono_class_from_mono_type (type);
13980
13981                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13982                 ensure_complete_type (field->parent, error);
13983                 if (!is_ok (error)) {
13984                         mono_metadata_free_type (type);
13985                         return NULL;
13986                 }
13987
13988                 g_assert (result);
13989                 mono_metadata_free_type (type);
13990                 *handle_class = mono_defaults.fieldhandle_class;
13991         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13992                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13993                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
13994                 return_val_if_nok (error, NULL);
13995                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
13996                 return_val_if_nok (error, NULL);
13997
13998                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13999                 MonoMethod *method;
14000
14001                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14002                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14003                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14004                         method = ((MonoReflectionMethod *)c->cb)->method;
14005                 else
14006                         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)));
14007
14008                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14009                 *handle_class = mono_defaults.methodhandle_class;
14010                 mono_metadata_free_type (type);
14011         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14012                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14013                 if (m->method_args) {
14014                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14015                         return_val_if_nok (error, NULL);
14016                         if (context) {
14017                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14018                                 mono_error_assert_ok (error);
14019                         }
14020                 } else {
14021                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14022                         return_val_if_nok (error, NULL);
14023                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14024                         return_val_if_nok (error, NULL);
14025
14026                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
14027                         MonoMethod *method;
14028
14029                         if (is_sre_method_builder (mono_object_class (m->mb)))
14030                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14031                         else if (is_sr_mono_method (mono_object_class (m->mb)))
14032                                 method = ((MonoReflectionMethod *)m->mb)->method;
14033                         else
14034                                 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)));
14035
14036                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14037                         mono_metadata_free_type (type);
14038                 }
14039                 *handle_class = mono_defaults.methodhandle_class;
14040         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14041                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14042                 MonoType *mtype;
14043                 MonoClass *klass;
14044                 MonoMethod *method;
14045                 gpointer iter;
14046                 char *name;
14047
14048                 mtype = mono_reflection_type_get_handle (m->parent, error);
14049                 return_val_if_nok (error, NULL);
14050                 klass = mono_class_from_mono_type (mtype);
14051
14052                 /* Find the method */
14053
14054                 name = mono_string_to_utf8 (m->name);
14055                 iter = NULL;
14056                 while ((method = mono_class_get_methods (klass, &iter))) {
14057                         if (!strcmp (method->name, name))
14058                                 break;
14059                 }
14060                 g_free (name);
14061
14062                 // FIXME:
14063                 g_assert (method);
14064                 // FIXME: Check parameters/return value etc. match
14065
14066                 result = method;
14067                 *handle_class = mono_defaults.methodhandle_class;
14068         } else if (is_sre_array (mono_object_get_class(obj)) ||
14069                                 is_sre_byref (mono_object_get_class(obj)) ||
14070                                 is_sre_pointer (mono_object_get_class(obj))) {
14071                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14072                 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14073                 return_val_if_nok (error, NULL);
14074
14075                 if (context) {
14076                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14077                         return_val_if_nok (error, NULL);
14078
14079                         result = mono_class_from_mono_type (inflated);
14080                         mono_metadata_free_type (inflated);
14081                 } else {
14082                         result = mono_class_from_mono_type (type);
14083                 }
14084                 *handle_class = mono_defaults.typehandle_class;
14085         } else {
14086                 g_print ("%s\n", obj->vtable->klass->name);
14087                 g_assert_not_reached ();
14088         }
14089         return result;
14090 }
14091
14092 #else /* DISABLE_REFLECTION_EMIT */
14093
14094 MonoArray*
14095 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
14096 {
14097         g_assert_not_reached ();
14098         return NULL;
14099 }
14100
14101 void
14102 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14103 {
14104         g_assert_not_reached ();
14105 }
14106
14107 void
14108 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14109 {
14110         g_assert_not_reached ();
14111 }
14112
14113 void
14114 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
14115 {
14116         g_assert_not_reached ();
14117 }
14118
14119 void
14120 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14121 {
14122         g_assert_not_reached ();
14123 }
14124
14125 void
14126 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14127 {
14128         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14129 }
14130
14131 void
14132 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14133 {
14134         g_assert_not_reached ();
14135 }
14136
14137 void
14138 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14139 {
14140         g_assert_not_reached ();
14141 }
14142
14143 MonoReflectionModule *
14144 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14145 {
14146         g_assert_not_reached ();
14147         return NULL;
14148 }
14149
14150 guint32
14151 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14152 {
14153         g_assert_not_reached ();
14154         return 0;
14155 }
14156
14157 guint32
14158 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14159 {
14160         g_assert_not_reached ();
14161         return 0;
14162 }
14163
14164 guint32
14165 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
14166                          gboolean create_open_instance, gboolean register_token, MonoError *error)
14167 {
14168         g_assert_not_reached ();
14169         return 0;
14170 }
14171
14172 void
14173 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14174 {
14175 }
14176
14177 void
14178 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14179 {
14180         g_assert_not_reached ();
14181 }
14182
14183 void
14184 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14185 {
14186         mono_error_init (error);
14187         *overrides = NULL;
14188         *num_overrides = 0;
14189 }
14190
14191 MonoReflectionEvent *
14192 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14193 {
14194         g_assert_not_reached ();
14195         return NULL;
14196 }
14197
14198 MonoReflectionType*
14199 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14200 {
14201         g_assert_not_reached ();
14202         return NULL;
14203 }
14204
14205 void
14206 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14207 {
14208         g_assert_not_reached ();
14209 }
14210
14211 MonoArray *
14212 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14213 {
14214         g_assert_not_reached ();
14215         return NULL;
14216 }
14217
14218 MonoArray *
14219 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14220 {
14221         g_assert_not_reached ();
14222         return NULL;
14223 }
14224
14225 void 
14226 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14227 {
14228 }
14229
14230 gpointer
14231 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
14232 {
14233         return NULL;
14234 }
14235
14236 MonoType*
14237 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14238 {
14239         mono_error_init (error);
14240         if (!ref)
14241                 return NULL;
14242         return ref->type;
14243 }
14244
14245 void
14246 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14247 {
14248         g_assert_not_reached ();
14249 }
14250
14251 #endif /* DISABLE_REFLECTION_EMIT */
14252
14253 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14254 const static guint32 declsec_flags_map[] = {
14255         0x00000000,                                     /* empty */
14256         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
14257         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
14258         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
14259         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
14260         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
14261         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
14262         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
14263         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
14264         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
14265         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
14266         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
14267         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
14268         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
14269         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
14270         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
14271         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
14272         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
14273         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
14274 };
14275
14276 /*
14277  * Returns flags that includes all available security action associated to the handle.
14278  * @token: metadata token (either for a class or a method)
14279  * @image: image where resides the metadata.
14280  */
14281 static guint32
14282 mono_declsec_get_flags (MonoImage *image, guint32 token)
14283 {
14284         int index = mono_metadata_declsec_from_index (image, token);
14285         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14286         guint32 result = 0;
14287         guint32 action;
14288         int i;
14289
14290         /* HasSecurity can be present for other, not specially encoded, attributes,
14291            e.g. SuppressUnmanagedCodeSecurityAttribute */
14292         if (index < 0)
14293                 return 0;
14294
14295         for (i = index; i < t->rows; i++) {
14296                 guint32 cols [MONO_DECL_SECURITY_SIZE];
14297
14298                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14299                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14300                         break;
14301
14302                 action = cols [MONO_DECL_SECURITY_ACTION];
14303                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14304                         result |= declsec_flags_map [action];
14305                 } else {
14306                         g_assert_not_reached ();
14307                 }
14308         }
14309         return result;
14310 }
14311
14312 /*
14313  * Get the security actions (in the form of flags) associated with the specified method.
14314  *
14315  * @method: The method for which we want the declarative security flags.
14316  * Return the declarative security flags for the method (only).
14317  *
14318  * Note: To keep MonoMethod size down we do not cache the declarative security flags
14319  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
14320  */
14321 guint32
14322 mono_declsec_flags_from_method (MonoMethod *method)
14323 {
14324         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14325                 /* FIXME: No cache (for the moment) */
14326                 guint32 idx = mono_method_get_index (method);
14327                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14328                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14329                 return mono_declsec_get_flags (method->klass->image, idx);
14330         }
14331         return 0;
14332 }
14333
14334 /*
14335  * Get the security actions (in the form of flags) associated with the specified class.
14336  *
14337  * @klass: The class for which we want the declarative security flags.
14338  * Return the declarative security flags for the class.
14339  *
14340  * Note: We cache the flags inside the MonoClass structure as this will get 
14341  *       called very often (at least for each method).
14342  */
14343 guint32
14344 mono_declsec_flags_from_class (MonoClass *klass)
14345 {
14346         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14347                 if (!klass->ext || !klass->ext->declsec_flags) {
14348                         guint32 idx;
14349
14350                         idx = mono_metadata_token_index (klass->type_token);
14351                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14352                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14353                         mono_loader_lock ();
14354                         mono_class_alloc_ext (klass);
14355                         mono_loader_unlock ();
14356                         /* we cache the flags on classes */
14357                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14358                 }
14359                 return klass->ext->declsec_flags;
14360         }
14361         return 0;
14362 }
14363
14364 /*
14365  * Get the security actions (in the form of flags) associated with the specified assembly.
14366  *
14367  * @assembly: The assembly for which we want the declarative security flags.
14368  * Return the declarative security flags for the assembly.
14369  */
14370 guint32
14371 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14372 {
14373         guint32 idx = 1; /* there is only one assembly */
14374         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14375         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14376         return mono_declsec_get_flags (assembly->image, idx);
14377 }
14378
14379
14380 /*
14381  * Fill actions for the specific index (which may either be an encoded class token or
14382  * an encoded method token) from the metadata image.
14383  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14384  */
14385 static MonoBoolean
14386 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14387         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14388 {
14389         MonoBoolean result = FALSE;
14390         MonoTableInfo *t;
14391         guint32 cols [MONO_DECL_SECURITY_SIZE];
14392         int index = mono_metadata_declsec_from_index (image, token);
14393         int i;
14394
14395         t  = &image->tables [MONO_TABLE_DECLSECURITY];
14396         for (i = index; i < t->rows; i++) {
14397                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14398
14399                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14400                         return result;
14401
14402                 /* if present only replace (class) permissions with method permissions */
14403                 /* if empty accept either class or method permissions */
14404                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14405                         if (!actions->demand.blob) {
14406                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14407                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14408                                 actions->demand.blob = (char*) (blob + 2);
14409                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14410                                 result = TRUE;
14411                         }
14412                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14413                         if (!actions->noncasdemand.blob) {
14414                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14415                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14416                                 actions->noncasdemand.blob = (char*) (blob + 2);
14417                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14418                                 result = TRUE;
14419                         }
14420                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14421                         if (!actions->demandchoice.blob) {
14422                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14423                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14424                                 actions->demandchoice.blob = (char*) (blob + 2);
14425                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14426                                 result = TRUE;
14427                         }
14428                 }
14429         }
14430
14431         return result;
14432 }
14433
14434 static MonoBoolean
14435 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14436         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14437 {
14438         guint32 idx = mono_metadata_token_index (klass->type_token);
14439         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14440         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14441         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14442 }
14443
14444 static MonoBoolean
14445 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14446         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14447 {
14448         guint32 idx = mono_method_get_index (method);
14449         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14450         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14451         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14452 }
14453
14454 /*
14455  * Collect all actions (that requires to generate code in mini) assigned for
14456  * the specified method.
14457  * Note: Don't use the content of actions if the function return FALSE.
14458  */
14459 MonoBoolean
14460 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14461 {
14462         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14463                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14464         MonoBoolean result = FALSE;
14465         guint32 flags;
14466
14467         /* quick exit if no declarative security is present in the metadata */
14468         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14469                 return FALSE;
14470
14471         /* we want the original as the wrapper is "free" of the security informations */
14472         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14473                 method = mono_marshal_method_from_wrapper (method);
14474                 if (!method)
14475                         return FALSE;
14476         }
14477
14478         /* First we look for method-level attributes */
14479         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14480                 mono_class_init (method->klass);
14481                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14482
14483                 result = mono_declsec_get_method_demands_params (method, demands, 
14484                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14485         }
14486
14487         /* Here we use (or create) the class declarative cache to look for demands */
14488         flags = mono_declsec_flags_from_class (method->klass);
14489         if (flags & mask) {
14490                 if (!result) {
14491                         mono_class_init (method->klass);
14492                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14493                 }
14494                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14495                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14496         }
14497
14498         /* The boolean return value is used as a shortcut in case nothing needs to
14499            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14500         return result;
14501 }
14502
14503
14504 /*
14505  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14506  *
14507  * Note: Don't use the content of actions if the function return FALSE.
14508  */
14509 MonoBoolean
14510 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14511 {
14512         MonoBoolean result = FALSE;
14513         guint32 flags;
14514
14515         /* quick exit if no declarative security is present in the metadata */
14516         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14517                 return FALSE;
14518
14519         /* we want the original as the wrapper is "free" of the security informations */
14520         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14521                 method = mono_marshal_method_from_wrapper (method);
14522                 if (!method)
14523                         return FALSE;
14524         }
14525
14526         /* results are independant - zeroize both */
14527         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14528         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14529
14530         /* First we look for method-level attributes */
14531         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14532                 mono_class_init (method->klass);
14533
14534                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14535                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14536         }
14537
14538         /* Here we use (or create) the class declarative cache to look for demands */
14539         flags = mono_declsec_flags_from_class (method->klass);
14540         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14541                 mono_class_init (method->klass);
14542
14543                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14544                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14545         }
14546
14547         return result;
14548 }
14549
14550 /*
14551  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14552  *
14553  * @klass       The inherited class - this is the class that provides the security check (attributes)
14554  * @demans      
14555  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14556  * 
14557  * Note: Don't use the content of actions if the function return FALSE.
14558  */
14559 MonoBoolean
14560 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14561 {
14562         MonoBoolean result = FALSE;
14563         guint32 flags;
14564
14565         /* quick exit if no declarative security is present in the metadata */
14566         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14567                 return FALSE;
14568
14569         /* Here we use (or create) the class declarative cache to look for demands */
14570         flags = mono_declsec_flags_from_class (klass);
14571         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14572                 mono_class_init (klass);
14573                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14574
14575                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14576                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14577         }
14578
14579         return result;
14580 }
14581
14582 /*
14583  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14584  *
14585  * Note: Don't use the content of actions if the function return FALSE.
14586  */
14587 MonoBoolean
14588 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14589 {
14590         /* quick exit if no declarative security is present in the metadata */
14591         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14592                 return FALSE;
14593
14594         /* we want the original as the wrapper is "free" of the security informations */
14595         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14596                 method = mono_marshal_method_from_wrapper (method);
14597                 if (!method)
14598                         return FALSE;
14599         }
14600
14601         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14602                 mono_class_init (method->klass);
14603                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14604
14605                 return mono_declsec_get_method_demands_params (method, demands, 
14606                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14607         }
14608         return FALSE;
14609 }
14610
14611
14612 static MonoBoolean
14613 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14614 {
14615         guint32 cols [MONO_DECL_SECURITY_SIZE];
14616         MonoTableInfo *t;
14617         int i;
14618
14619         int index = mono_metadata_declsec_from_index (image, token);
14620         if (index == -1)
14621                 return FALSE;
14622
14623         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14624         for (i = index; i < t->rows; i++) {
14625                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14626
14627                 /* shortcut - index are ordered */
14628                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14629                         return FALSE;
14630
14631                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14632                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14633                         entry->blob = (char*) (metadata + 2);
14634                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14635                         return TRUE;
14636                 }
14637         }
14638
14639         return FALSE;
14640 }
14641
14642 MonoBoolean
14643 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14644 {
14645         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14646                 guint32 idx = mono_method_get_index (method);
14647                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14648                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14649                 return get_declsec_action (method->klass->image, idx, action, entry);
14650         }
14651         return FALSE;
14652 }
14653
14654 MonoBoolean
14655 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14656 {
14657         /* use cache */
14658         guint32 flags = mono_declsec_flags_from_class (klass);
14659         if (declsec_flags_map [action] & flags) {
14660                 guint32 idx = mono_metadata_token_index (klass->type_token);
14661                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14662                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14663                 return get_declsec_action (klass->image, idx, action, entry);
14664         }
14665         return FALSE;
14666 }
14667
14668 MonoBoolean
14669 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14670 {
14671         guint32 idx = 1; /* there is only one assembly */
14672         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14673         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14674
14675         return get_declsec_action (assembly->image, idx, action, entry);
14676 }
14677
14678 gboolean
14679 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14680 {
14681         MonoObject *res, *exc;
14682         void *params [1];
14683         static MonoMethod *method = NULL;
14684
14685         mono_error_init (error);
14686
14687         if (method == NULL) {
14688                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14689                 g_assert (method);
14690         }
14691
14692         /* 
14693          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14694          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14695          */
14696         g_assert (mono_class_get_ref_info (klass));
14697         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14698
14699         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14700         return_val_if_nok (error, FALSE);
14701
14702         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
14703
14704         if (exc || !mono_error_ok (error)) {
14705                 mono_error_cleanup (error);
14706                 return FALSE;
14707         } else
14708                 return *(MonoBoolean*)mono_object_unbox (res);
14709 }
14710
14711 /**
14712  * mono_reflection_type_get_type:
14713  * @reftype: the System.Type object
14714  *
14715  * Returns the MonoType* associated with the C# System.Type object @reftype.
14716  */
14717 MonoType*
14718 mono_reflection_type_get_type (MonoReflectionType *reftype)
14719 {
14720         g_assert (reftype);
14721
14722         MonoError error;
14723         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14724         mono_error_assert_ok (&error);
14725         return result;
14726 }
14727
14728 /**
14729  * mono_reflection_assembly_get_assembly:
14730  * @refassembly: the System.Reflection.Assembly object
14731  *
14732  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14733  */
14734 MonoAssembly*
14735 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14736 {
14737         g_assert (refassembly);
14738
14739         return refassembly->assembly;
14740 }
14741