[SRE] MonoError in encode_locals
[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);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
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);
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);
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);
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 #ifndef DISABLE_REFLECTION_EMIT
428 static char*
429 image_strdup (MonoImage *image, const char *s)
430 {
431         MONO_REQ_GC_NEUTRAL_MODE;
432
433         if (image)
434                 return mono_image_strdup (image, s);
435         else
436                 return g_strdup (s);
437 }
438 #endif
439
440 #define image_g_new(image,struct_type, n_structs)               \
441     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
442
443 #define image_g_new0(image,struct_type, n_structs)              \
444     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
445
446
447 static void
448 alloc_table (MonoDynamicTable *table, guint nrows)
449 {
450         MONO_REQ_GC_NEUTRAL_MODE;
451
452         table->rows = nrows;
453         g_assert (table->columns);
454         if (nrows + 1 >= table->alloc_rows) {
455                 while (nrows + 1 >= table->alloc_rows) {
456                         if (table->alloc_rows == 0)
457                                 table->alloc_rows = 16;
458                         else
459                                 table->alloc_rows *= 2;
460                 }
461
462                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
463         }
464 }
465
466 static void
467 make_room_in_stream (MonoDynamicStream *stream, int size)
468 {
469         MONO_REQ_GC_NEUTRAL_MODE;
470
471         if (size <= stream->alloc_size)
472                 return;
473         
474         while (stream->alloc_size <= size) {
475                 if (stream->alloc_size < 4096)
476                         stream->alloc_size = 4096;
477                 else
478                         stream->alloc_size *= 2;
479         }
480         
481         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
482 }
483
484 static guint32
485 string_heap_insert (MonoDynamicStream *sh, const char *str)
486 {
487         MONO_REQ_GC_NEUTRAL_MODE;
488
489         guint32 idx;
490         guint32 len;
491         gpointer oldkey, oldval;
492
493         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
494                 return GPOINTER_TO_UINT (oldval);
495
496         len = strlen (str) + 1;
497         idx = sh->index;
498         
499         make_room_in_stream (sh, idx + len);
500
501         /*
502          * We strdup the string even if we already copy them in sh->data
503          * so that the string pointers in the hash remain valid even if
504          * we need to realloc sh->data. We may want to avoid that later.
505          */
506         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
507         memcpy (sh->data + idx, str, len);
508         sh->index += len;
509         return idx;
510 }
511
512 static guint32
513 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
514 {
515         MONO_REQ_GC_UNSAFE_MODE;
516
517         char *name = mono_string_to_utf8 (str);
518         guint32 idx;
519         idx = string_heap_insert (sh, name);
520         g_free (name);
521         return idx;
522 }
523
524 #ifndef DISABLE_REFLECTION_EMIT
525 static void
526 string_heap_init (MonoDynamicStream *sh)
527 {
528         MONO_REQ_GC_NEUTRAL_MODE;
529
530         sh->index = 0;
531         sh->alloc_size = 4096;
532         sh->data = (char *)g_malloc (4096);
533         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
534         string_heap_insert (sh, "");
535 }
536 #endif
537
538 static guint32
539 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
540 {
541         MONO_REQ_GC_NEUTRAL_MODE;
542
543         guint32 idx;
544         
545         make_room_in_stream (stream, stream->index + len);
546         memcpy (stream->data + stream->index, data, len);
547         idx = stream->index;
548         stream->index += len;
549         /* 
550          * align index? Not without adding an additional param that controls it since
551          * we may store a blob value in pieces.
552          */
553         return idx;
554 }
555
556 static guint32
557 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
558 {
559         MONO_REQ_GC_NEUTRAL_MODE;
560
561         guint32 idx;
562         
563         make_room_in_stream (stream, stream->index + len);
564         memset (stream->data + stream->index, 0, len);
565         idx = stream->index;
566         stream->index += len;
567         return idx;
568 }
569
570 static void
571 stream_data_align (MonoDynamicStream *stream)
572 {
573         MONO_REQ_GC_NEUTRAL_MODE;
574
575         char buf [4] = {0};
576         guint32 count = stream->index % 4;
577
578         /* we assume the stream data will be aligned */
579         if (count)
580                 mono_image_add_stream_data (stream, buf, 4 - count);
581 }
582
583 #ifndef DISABLE_REFLECTION_EMIT
584 static int
585 mono_blob_entry_hash (const char* str)
586 {
587         MONO_REQ_GC_NEUTRAL_MODE;
588
589         guint len, h;
590         const char *end;
591         len = mono_metadata_decode_blob_size (str, &str);
592         if (len > 0) {
593                 end = str + len;
594                 h = *str;
595                 for (str += 1; str < end; str++)
596                         h = (h << 5) - h + *str;
597                 return h;
598         } else {
599                 return 0;
600         }
601 }
602
603 static gboolean
604 mono_blob_entry_equal (const char *str1, const char *str2) {
605         MONO_REQ_GC_NEUTRAL_MODE;
606
607         int len, len2;
608         const char *end1;
609         const char *end2;
610         len = mono_metadata_decode_blob_size (str1, &end1);
611         len2 = mono_metadata_decode_blob_size (str2, &end2);
612         if (len != len2)
613                 return 0;
614         return memcmp (end1, end2, len) == 0;
615 }
616 #endif
617 static guint32
618 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
619 {
620         MONO_REQ_GC_NEUTRAL_MODE;
621
622         guint32 idx;
623         char *copy;
624         gpointer oldkey, oldval;
625
626         copy = (char *)g_malloc (s1+s2);
627         memcpy (copy, b1, s1);
628         memcpy (copy + s1, b2, s2);
629         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
630                 g_free (copy);
631                 idx = GPOINTER_TO_UINT (oldval);
632         } else {
633                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
634                 mono_image_add_stream_data (&assembly->blob, b2, s2);
635                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
636         }
637         return idx;
638 }
639
640 static guint32
641 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
642 {
643         MONO_REQ_GC_NEUTRAL_MODE;
644
645         char blob_size [8];
646         char *b = blob_size;
647         guint32 size = buf->p - buf->buf;
648         /* store length */
649         g_assert (size <= (buf->end - buf->buf));
650         mono_metadata_encode_value (size, b, &b);
651         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
652 }
653
654 /*
655  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
656  * dest may be misaligned.
657  */
658 static void
659 swap_with_size (char *dest, const char* val, int len, int nelem) {
660         MONO_REQ_GC_NEUTRAL_MODE;
661 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
662         int elem;
663
664         for (elem = 0; elem < nelem; ++elem) {
665                 switch (len) {
666                 case 1:
667                         *dest = *val;
668                         break;
669                 case 2:
670                         dest [0] = val [1];
671                         dest [1] = val [0];
672                         break;
673                 case 4:
674                         dest [0] = val [3];
675                         dest [1] = val [2];
676                         dest [2] = val [1];
677                         dest [3] = val [0];
678                         break;
679                 case 8:
680                         dest [0] = val [7];
681                         dest [1] = val [6];
682                         dest [2] = val [5];
683                         dest [3] = val [4];
684                         dest [4] = val [3];
685                         dest [5] = val [2];
686                         dest [6] = val [1];
687                         dest [7] = val [0];
688                         break;
689                 default:
690                         g_assert_not_reached ();
691                 }
692                 dest += len;
693                 val += len;
694         }
695 #else
696         memcpy (dest, val, len * nelem);
697 #endif
698 }
699
700 static guint32
701 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
702 {
703         MONO_REQ_GC_UNSAFE_MODE;
704         
705         char blob_size [64];
706         char *b = blob_size;
707         guint32 idx = 0, len;
708
709         len = str->length * 2;
710         mono_metadata_encode_value (len, b, &b);
711 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
712         {
713                 char *swapped = g_malloc (2 * mono_string_length (str));
714                 const char *p = (const char*)mono_string_chars (str);
715
716                 swap_with_size (swapped, p, 2, mono_string_length (str));
717                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
718                 g_free (swapped);
719         }
720 #else
721         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
722 #endif
723         return idx;
724 }
725
726 #ifndef DISABLE_REFLECTION_EMIT
727 static MonoClass *
728 default_class_from_mono_type (MonoType *type)
729 {
730         MONO_REQ_GC_NEUTRAL_MODE;
731
732         switch (type->type) {
733         case MONO_TYPE_OBJECT:
734                 return mono_defaults.object_class;
735         case MONO_TYPE_VOID:
736                 return mono_defaults.void_class;
737         case MONO_TYPE_BOOLEAN:
738                 return mono_defaults.boolean_class;
739         case MONO_TYPE_CHAR:
740                 return mono_defaults.char_class;
741         case MONO_TYPE_I1:
742                 return mono_defaults.sbyte_class;
743         case MONO_TYPE_U1:
744                 return mono_defaults.byte_class;
745         case MONO_TYPE_I2:
746                 return mono_defaults.int16_class;
747         case MONO_TYPE_U2:
748                 return mono_defaults.uint16_class;
749         case MONO_TYPE_I4:
750                 return mono_defaults.int32_class;
751         case MONO_TYPE_U4:
752                 return mono_defaults.uint32_class;
753         case MONO_TYPE_I:
754                 return mono_defaults.int_class;
755         case MONO_TYPE_U:
756                 return mono_defaults.uint_class;
757         case MONO_TYPE_I8:
758                 return mono_defaults.int64_class;
759         case MONO_TYPE_U8:
760                 return mono_defaults.uint64_class;
761         case MONO_TYPE_R4:
762                 return mono_defaults.single_class;
763         case MONO_TYPE_R8:
764                 return mono_defaults.double_class;
765         case MONO_TYPE_STRING:
766                 return mono_defaults.string_class;
767         default:
768                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
769                 g_assert_not_reached ();
770         }
771         
772         return NULL;
773 }
774 #endif
775
776 /*
777  * mono_class_get_ref_info:
778  *
779  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
780  */
781 gpointer
782 mono_class_get_ref_info (MonoClass *klass)
783 {
784         MONO_REQ_GC_UNSAFE_MODE;
785
786         if (klass->ref_info_handle == 0)
787                 return NULL;
788         else
789                 return mono_gchandle_get_target (klass->ref_info_handle);
790 }
791
792 void
793 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
794 {
795         MONO_REQ_GC_UNSAFE_MODE;
796
797         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
798         g_assert (klass->ref_info_handle != 0);
799 }
800
801 void
802 mono_class_free_ref_info (MonoClass *klass)
803 {
804         MONO_REQ_GC_NEUTRAL_MODE;
805
806         if (klass->ref_info_handle) {
807                 mono_gchandle_free (klass->ref_info_handle);
808                 klass->ref_info_handle = 0;
809         }
810 }
811
812 static void
813 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
814 {
815         MONO_REQ_GC_NEUTRAL_MODE;
816
817         int i;
818         MonoGenericInst *class_inst;
819         MonoClass *klass;
820
821         g_assert (gclass);
822
823         class_inst = gclass->context.class_inst;
824
825         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
826         klass = gclass->container_class;
827         sigbuffer_add_value (buf, klass->byval_arg.type);
828         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
829
830         sigbuffer_add_value (buf, class_inst->type_argc);
831         for (i = 0; i < class_inst->type_argc; ++i)
832                 encode_type (assembly, class_inst->type_argv [i], buf);
833
834 }
835
836 static void
837 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
838 {
839         MONO_REQ_GC_NEUTRAL_MODE;
840
841         if (!type) {
842                 g_assert_not_reached ();
843                 return;
844         }
845                 
846         if (type->byref)
847                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
848
849         switch (type->type){
850         case MONO_TYPE_VOID:
851         case MONO_TYPE_BOOLEAN:
852         case MONO_TYPE_CHAR:
853         case MONO_TYPE_I1:
854         case MONO_TYPE_U1:
855         case MONO_TYPE_I2:
856         case MONO_TYPE_U2:
857         case MONO_TYPE_I4:
858         case MONO_TYPE_U4:
859         case MONO_TYPE_I8:
860         case MONO_TYPE_U8:
861         case MONO_TYPE_R4:
862         case MONO_TYPE_R8:
863         case MONO_TYPE_I:
864         case MONO_TYPE_U:
865         case MONO_TYPE_STRING:
866         case MONO_TYPE_OBJECT:
867         case MONO_TYPE_TYPEDBYREF:
868                 sigbuffer_add_value (buf, type->type);
869                 break;
870         case MONO_TYPE_PTR:
871                 sigbuffer_add_value (buf, type->type);
872                 encode_type (assembly, type->data.type, buf);
873                 break;
874         case MONO_TYPE_SZARRAY:
875                 sigbuffer_add_value (buf, type->type);
876                 encode_type (assembly, &type->data.klass->byval_arg, buf);
877                 break;
878         case MONO_TYPE_VALUETYPE:
879         case MONO_TYPE_CLASS: {
880                 MonoClass *k = mono_class_from_mono_type (type);
881
882                 if (k->generic_container) {
883                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
884                         encode_generic_class (assembly, gclass, buf);
885                 } else {
886                         /*
887                          * Make sure we use the correct type.
888                          */
889                         sigbuffer_add_value (buf, k->byval_arg.type);
890                         /*
891                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
892                          * otherwise two typerefs could point to the same type, leading to
893                          * verification errors.
894                          */
895                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
896                 }
897                 break;
898         }
899         case MONO_TYPE_ARRAY:
900                 sigbuffer_add_value (buf, type->type);
901                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
902                 sigbuffer_add_value (buf, type->data.array->rank);
903                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
904                 sigbuffer_add_value (buf, 0);
905                 break;
906         case MONO_TYPE_GENERICINST:
907                 encode_generic_class (assembly, type->data.generic_class, buf);
908                 break;
909         case MONO_TYPE_VAR:
910         case MONO_TYPE_MVAR:
911                 sigbuffer_add_value (buf, type->type);
912                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
913                 break;
914         default:
915                 g_error ("need to encode type %x", type->type);
916         }
917 }
918
919 static void
920 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
921 {
922         MONO_REQ_GC_UNSAFE_MODE;
923
924         mono_error_init (error);
925
926         if (!type) {
927                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
928                 return;
929         }
930
931         MonoType *t = mono_reflection_type_get_handle (type, error);
932         return_if_nok (error);
933         encode_type (assembly, t, buf);
934 }
935
936 static void
937 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
938 {
939         MONO_REQ_GC_UNSAFE_MODE;
940
941         int i;
942
943         mono_error_init (error);
944
945         if (modreq) {
946                 for (i = 0; i < mono_array_length (modreq); ++i) {
947                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
948                         return_if_nok (error);
949                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
950                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
951                 }
952         }
953         if (modopt) {
954                 for (i = 0; i < mono_array_length (modopt); ++i) {
955                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
956                         return_if_nok (error);
957                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
958                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
959                 }
960         }
961 }
962
963 #ifndef DISABLE_REFLECTION_EMIT
964 static guint32
965 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
966 {
967         MONO_REQ_GC_UNSAFE_MODE;
968
969         SigBuffer buf;
970         int i;
971         guint32 nparams =  sig->param_count;
972         guint32 idx;
973
974         if (!assembly->save)
975                 return 0;
976
977         sigbuffer_init (&buf, 32);
978         /*
979          * FIXME: vararg, explicit_this, differenc call_conv values...
980          */
981         idx = sig->call_convention;
982         if (sig->hasthis)
983                 idx |= 0x20; /* hasthis */
984         if (sig->generic_param_count)
985                 idx |= 0x10; /* generic */
986         sigbuffer_add_byte (&buf, idx);
987         if (sig->generic_param_count)
988                 sigbuffer_add_value (&buf, sig->generic_param_count);
989         sigbuffer_add_value (&buf, nparams);
990         encode_type (assembly, sig->ret, &buf);
991         for (i = 0; i < nparams; ++i) {
992                 if (i == sig->sentinelpos)
993                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
994                 encode_type (assembly, sig->params [i], &buf);
995         }
996         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
997         sigbuffer_free (&buf);
998         return idx;
999 }
1000 #endif
1001
1002 static guint32
1003 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1004 {
1005         MONO_REQ_GC_UNSAFE_MODE;
1006
1007         mono_error_init (error);
1008
1009         /*
1010          * FIXME: reuse code from method_encode_signature().
1011          */
1012         SigBuffer buf;
1013         int i;
1014         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1015         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1016         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1017         guint32 idx;
1018
1019         sigbuffer_init (&buf, 32);
1020         /* LAMESPEC: all the call conv spec is foobared */
1021         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1022         if (mb->call_conv & 2)
1023                 idx |= 0x5; /* vararg */
1024         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1025                 idx |= 0x20; /* hasthis */
1026         if (ngparams)
1027                 idx |= 0x10; /* generic */
1028         sigbuffer_add_byte (&buf, idx);
1029         if (ngparams)
1030                 sigbuffer_add_value (&buf, ngparams);
1031         sigbuffer_add_value (&buf, nparams + notypes);
1032         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1033         if (!is_ok (error))
1034                 goto leave;
1035         encode_reflection_type (assembly, mb->rtype, &buf, error);
1036         if (!is_ok (error))
1037                 goto leave;
1038         for (i = 0; i < nparams; ++i) {
1039                 MonoArray *modreq = NULL;
1040                 MonoArray *modopt = NULL;
1041                 MonoReflectionType *pt;
1042
1043                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1044                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1045                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1046                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1047                 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1048                 if (!is_ok (error))
1049                         goto leave;
1050                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1051                 encode_reflection_type (assembly, pt, &buf, error);
1052                 if (!is_ok (error))
1053                         goto leave;
1054         }
1055         if (notypes)
1056                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1057         for (i = 0; i < notypes; ++i) {
1058                 MonoReflectionType *pt;
1059
1060                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1061                 encode_reflection_type (assembly, pt, &buf, error);
1062                 if (!is_ok (error))
1063                         goto leave;
1064         }
1065
1066         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1067 leave:
1068         sigbuffer_free (&buf);
1069         return idx;
1070 }
1071
1072 static guint32
1073 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1074 {
1075         MONO_REQ_GC_UNSAFE_MODE;
1076
1077         mono_error_init (error);
1078
1079         MonoDynamicTable *table;
1080         guint32 *values;
1081         guint32 idx, sig_idx;
1082         guint nl = mono_array_length (ilgen->locals);
1083         SigBuffer buf;
1084         int i;
1085
1086         sigbuffer_init (&buf, 32);
1087         sigbuffer_add_value (&buf, 0x07);
1088         sigbuffer_add_value (&buf, nl);
1089         for (i = 0; i < nl; ++i) {
1090                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1091                 
1092                 if (lb->is_pinned)
1093                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1094                 
1095                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1096                 if (!is_ok (error)) {
1097                         sigbuffer_free (&buf);
1098                         return 0;
1099                 }
1100         }
1101         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1102         sigbuffer_free (&buf);
1103
1104         if (assembly->standalonesig_cache == NULL)
1105                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1106         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1107         if (idx)
1108                 return idx;
1109
1110         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1111         idx = table->next_idx ++;
1112         table->rows ++;
1113         alloc_table (table, table->rows);
1114         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1115
1116         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1117
1118         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1119
1120         return idx;
1121 }
1122
1123 static guint32
1124 method_count_clauses (MonoReflectionILGen *ilgen)
1125 {
1126         MONO_REQ_GC_UNSAFE_MODE;
1127
1128         guint32 num_clauses = 0;
1129         int i;
1130
1131         MonoILExceptionInfo *ex_info;
1132         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1133                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1134                 if (ex_info->handlers)
1135                         num_clauses += mono_array_length (ex_info->handlers);
1136                 else
1137                         num_clauses++;
1138         }
1139
1140         return num_clauses;
1141 }
1142
1143 #ifndef DISABLE_REFLECTION_EMIT
1144 static MonoExceptionClause*
1145 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1146 {
1147         MONO_REQ_GC_UNSAFE_MODE;
1148
1149         MonoError error;
1150         MonoExceptionClause *clauses;
1151         MonoExceptionClause *clause;
1152         MonoILExceptionInfo *ex_info;
1153         MonoILExceptionBlock *ex_block;
1154         guint32 finally_start;
1155         int i, j, clause_index;;
1156
1157         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1158
1159         clause_index = 0;
1160         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1161                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1162                 finally_start = ex_info->start + ex_info->len;
1163                 if (!ex_info->handlers)
1164                         continue;
1165                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1166                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1167                         clause = &(clauses [clause_index]);
1168
1169                         clause->flags = ex_block->type;
1170                         clause->try_offset = ex_info->start;
1171
1172                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1173                                 clause->try_len = finally_start - ex_info->start;
1174                         else
1175                                 clause->try_len = ex_info->len;
1176                         clause->handler_offset = ex_block->start;
1177                         clause->handler_len = ex_block->len;
1178                         if (ex_block->extype) {
1179                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, &error);
1180                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
1181                                 clause->data.catch_class = mono_class_from_mono_type (extype);
1182                         } else {
1183                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1184                                         clause->data.filter_offset = ex_block->filter_offset;
1185                                 else
1186                                         clause->data.filter_offset = 0;
1187                         }
1188                         finally_start = ex_block->start + ex_block->len;
1189
1190                         clause_index ++;
1191                 }
1192         }
1193
1194         return clauses;
1195 }
1196 #endif /* !DISABLE_REFLECTION_EMIT */
1197
1198 /**
1199  * method_encode_code:
1200  *
1201  * @assembly the assembly
1202  * @mb the managed MethodBuilder
1203  * @error set on error
1204  *
1205  * Note that the return value is not sensible if @error is set.
1206  */
1207 static guint32
1208 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1209 {
1210         MONO_REQ_GC_UNSAFE_MODE;
1211
1212         char flags = 0;
1213         guint32 idx;
1214         guint32 code_size;
1215         gint32 max_stack, i;
1216         gint32 num_locals = 0;
1217         gint32 num_exception = 0;
1218         gint maybe_small;
1219         guint32 fat_flags;
1220         char fat_header [12];
1221         guint32 int_value;
1222         guint16 short_value;
1223         guint32 local_sig = 0;
1224         guint32 header_size = 12;
1225         MonoArray *code;
1226
1227         mono_error_init (error);
1228
1229         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1230                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1231                 return 0;
1232
1233         /*if (mb->name)
1234                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1235         if (mb->ilgen) {
1236                 code = mb->ilgen->code;
1237                 code_size = mb->ilgen->code_len;
1238                 max_stack = mb->ilgen->max_stack;
1239                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1240                 if (mb->ilgen->ex_handlers)
1241                         num_exception = method_count_clauses (mb->ilgen);
1242         } else {
1243                 code = mb->code;
1244                 if (code == NULL){
1245                         char *name = mono_string_to_utf8 (mb->name);
1246                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1247                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1248                         g_free (str);
1249                         g_free (name);
1250                         return 0;
1251                 }
1252
1253                 code_size = mono_array_length (code);
1254                 max_stack = 8; /* we probably need to run a verifier on the code... */
1255         }
1256
1257         stream_data_align (&assembly->code);
1258
1259         /* check for exceptions, maxstack, locals */
1260         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1261         if (maybe_small) {
1262                 if (code_size < 64 && !(code_size & 1)) {
1263                         flags = (code_size << 2) | 0x2;
1264                 } else if (code_size < 32 && (code_size & 1)) {
1265                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1266                 } else {
1267                         goto fat_header;
1268                 }
1269                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1270                 /* add to the fixup todo list */
1271                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1272                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1273                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1274                 return assembly->text_rva + idx;
1275         } 
1276 fat_header:
1277         if (num_locals) {
1278                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1279                 return_val_if_nok (error, 0);
1280         }
1281         /* 
1282          * FIXME: need to set also the header size in fat_flags.
1283          * (and more sects and init locals flags)
1284          */
1285         fat_flags =  0x03;
1286         if (num_exception)
1287                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1288         if (mb->init_locals)
1289                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1290         fat_header [0] = fat_flags;
1291         fat_header [1] = (header_size / 4 ) << 4;
1292         short_value = GUINT16_TO_LE (max_stack);
1293         memcpy (fat_header + 2, &short_value, 2);
1294         int_value = GUINT32_TO_LE (code_size);
1295         memcpy (fat_header + 4, &int_value, 4);
1296         int_value = GUINT32_TO_LE (local_sig);
1297         memcpy (fat_header + 8, &int_value, 4);
1298         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1299         /* add to the fixup todo list */
1300         if (mb->ilgen && mb->ilgen->num_token_fixups)
1301                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1302         
1303         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1304         if (num_exception) {
1305                 unsigned char sheader [4];
1306                 MonoILExceptionInfo * ex_info;
1307                 MonoILExceptionBlock * ex_block;
1308                 int j;
1309
1310                 stream_data_align (&assembly->code);
1311                 /* always use fat format for now */
1312                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1313                 num_exception *= 6 * sizeof (guint32);
1314                 num_exception += 4; /* include the size of the header */
1315                 sheader [1] = num_exception & 0xff;
1316                 sheader [2] = (num_exception >> 8) & 0xff;
1317                 sheader [3] = (num_exception >> 16) & 0xff;
1318                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1319                 /* fat header, so we are already aligned */
1320                 /* reverse order */
1321                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1322                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1323                         if (ex_info->handlers) {
1324                                 int finally_start = ex_info->start + ex_info->len;
1325                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1326                                         guint32 val;
1327                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1328                                         /* the flags */
1329                                         val = GUINT32_TO_LE (ex_block->type);
1330                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1331                                         /* try offset */
1332                                         val = GUINT32_TO_LE (ex_info->start);
1333                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1334                                         /* need fault, too, probably */
1335                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1336                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1337                                         else
1338                                                 val = GUINT32_TO_LE (ex_info->len);
1339                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1340                                         /* handler offset */
1341                                         val = GUINT32_TO_LE (ex_block->start);
1342                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1343                                         /* handler len */
1344                                         val = GUINT32_TO_LE (ex_block->len);
1345                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1346                                         finally_start = ex_block->start + ex_block->len;
1347                                         if (ex_block->extype) {
1348                                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1349                                                 return_val_if_nok (error, 0);
1350
1351                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1352                                         } else {
1353                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1354                                                         val = ex_block->filter_offset;
1355                                                 else
1356                                                         val = 0;
1357                                         }
1358                                         val = GUINT32_TO_LE (val);
1359                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1360                                         /*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", 
1361                                                         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);*/
1362                                 }
1363                         } else {
1364                                 g_error ("No clauses for ex info block %d", i);
1365                         }
1366                 }
1367         }
1368         return assembly->text_rva + idx;
1369 }
1370
1371 static guint32
1372 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1373 {
1374         MONO_REQ_GC_NEUTRAL_MODE;
1375
1376         int i;
1377         MonoDynamicTable *table;
1378         guint32 *values;
1379         
1380         table = &assembly->tables [table_idx];
1381
1382         g_assert (col < table->columns);
1383
1384         values = table->values + table->columns;
1385         for (i = 1; i <= table->rows; ++i) {
1386                 if (values [col] == token)
1387                         return i;
1388                 values += table->columns;
1389         }
1390         return 0;
1391 }
1392
1393 /*
1394  * LOCKING: Acquires the loader lock. 
1395  */
1396 static MonoCustomAttrInfo*
1397 lookup_custom_attr (MonoImage *image, gpointer member)
1398 {
1399         MONO_REQ_GC_NEUTRAL_MODE;
1400
1401         MonoCustomAttrInfo* res;
1402
1403         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1404
1405         if (!res)
1406                 return NULL;
1407
1408         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1409         res->cached = 0;
1410         return res;
1411 }
1412
1413 static gboolean
1414 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1415 {
1416         MONO_REQ_GC_UNSAFE_MODE;
1417
1418         /* FIXME: Need to do more checks */
1419         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1420                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1421
1422                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1423                         return FALSE;
1424         }
1425
1426         return TRUE;
1427 }
1428
1429 static MonoCustomAttrInfo*
1430 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1431 {
1432         MONO_REQ_GC_UNSAFE_MODE;
1433
1434         int i, index, count, not_visible;
1435         MonoCustomAttrInfo *ainfo;
1436         MonoReflectionCustomAttr *cattr;
1437
1438         if (!cattrs)
1439                 return NULL;
1440         /* FIXME: check in assembly the Run flag is set */
1441
1442         count = mono_array_length (cattrs);
1443
1444         /* Skip nonpublic attributes since MS.NET seems to do the same */
1445         /* FIXME: This needs to be done more globally */
1446         not_visible = 0;
1447         for (i = 0; i < count; ++i) {
1448                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1449                 if (!custom_attr_visible (image, cattr))
1450                         not_visible ++;
1451         }
1452         count -= not_visible;
1453
1454         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1455
1456         ainfo->image = image;
1457         ainfo->num_attrs = count;
1458         ainfo->cached = alloc_img != NULL;
1459         index = 0;
1460         for (i = 0; i < count; ++i) {
1461                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1462                 if (custom_attr_visible (image, cattr)) {
1463                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1464                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1465                         ainfo->attrs [index].ctor = cattr->ctor->method;
1466                         ainfo->attrs [index].data = saved;
1467                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1468                         index ++;
1469                 }
1470         }
1471
1472         return ainfo;
1473 }
1474
1475 #ifndef DISABLE_REFLECTION_EMIT
1476 /*
1477  * LOCKING: Acquires the loader lock. 
1478  */
1479 static void
1480 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1481 {
1482         MONO_REQ_GC_UNSAFE_MODE;
1483
1484         MonoCustomAttrInfo *ainfo, *tmp;
1485
1486         if (!cattrs || !mono_array_length (cattrs))
1487                 return;
1488
1489         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1490
1491         mono_loader_lock ();
1492         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1493         if (tmp)
1494                 mono_custom_attrs_free (tmp);
1495         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1496         mono_loader_unlock ();
1497
1498 }
1499 #endif
1500
1501 void
1502 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1503 {
1504         MONO_REQ_GC_NEUTRAL_MODE;
1505
1506         if (ainfo && !ainfo->cached)
1507                 g_free (ainfo);
1508 }
1509
1510 /*
1511  * idx is the table index of the object
1512  * type is one of MONO_CUSTOM_ATTR_*
1513  */
1514 static gboolean
1515 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1516 {
1517         MONO_REQ_GC_UNSAFE_MODE;
1518
1519         MonoDynamicTable *table;
1520         MonoReflectionCustomAttr *cattr;
1521         guint32 *values;
1522         guint32 count, i, token;
1523         char blob_size [6];
1524         char *p = blob_size;
1525         
1526         mono_error_init (error);
1527
1528         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1529         if (!cattrs)
1530                 return TRUE;
1531         count = mono_array_length (cattrs);
1532         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1533         table->rows += count;
1534         alloc_table (table, table->rows);
1535         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1536         idx <<= MONO_CUSTOM_ATTR_BITS;
1537         idx |= type;
1538         for (i = 0; i < count; ++i) {
1539                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1540                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1541                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1542                 if (!mono_error_ok (error)) goto fail;
1543                 type = mono_metadata_token_index (token);
1544                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1545                 switch (mono_metadata_token_table (token)) {
1546                 case MONO_TABLE_METHOD:
1547                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1548                         /*
1549                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1550                          * method, not the one returned by mono_image_create_token ().
1551                          */
1552                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1553                         break;
1554                 case MONO_TABLE_MEMBERREF:
1555                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1556                         break;
1557                 default:
1558                         g_warning ("got wrong token in custom attr");
1559                         continue;
1560                 }
1561                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1562                 p = blob_size;
1563                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1564                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1565                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1566                 values += MONO_CUSTOM_ATTR_SIZE;
1567                 ++table->next_idx;
1568         }
1569
1570         return TRUE;
1571
1572 fail:
1573         return FALSE;
1574 }
1575
1576 static void
1577 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1578 {
1579         MONO_REQ_GC_UNSAFE_MODE;
1580
1581         MonoDynamicTable *table;
1582         guint32 *values;
1583         guint32 count, i, idx;
1584         MonoReflectionPermissionSet *perm;
1585
1586         if (!permissions)
1587                 return;
1588
1589         count = mono_array_length (permissions);
1590         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1591         table->rows += count;
1592         alloc_table (table, table->rows);
1593
1594         for (i = 0; i < mono_array_length (permissions); ++i) {
1595                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1596
1597                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1598
1599                 idx = mono_metadata_token_index (parent_token);
1600                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1601                 switch (mono_metadata_token_table (parent_token)) {
1602                 case MONO_TABLE_TYPEDEF:
1603                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1604                         break;
1605                 case MONO_TABLE_METHOD:
1606                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1607                         break;
1608                 case MONO_TABLE_ASSEMBLY:
1609                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1610                         break;
1611                 default:
1612                         g_assert_not_reached ();
1613                 }
1614
1615                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1616                 values [MONO_DECL_SECURITY_PARENT] = idx;
1617                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1618
1619                 ++table->next_idx;
1620         }
1621 }
1622
1623 /*
1624  * Fill in the MethodDef and ParamDef tables for a method.
1625  * This is used for both normal methods and constructors.
1626  */
1627 static gboolean
1628 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1629 {
1630         MONO_REQ_GC_UNSAFE_MODE;
1631
1632         MonoDynamicTable *table;
1633         guint32 *values;
1634         guint i, count;
1635
1636         mono_error_init (error);
1637
1638         /* room in this table is already allocated */
1639         table = &assembly->tables [MONO_TABLE_METHOD];
1640         *mb->table_idx = table->next_idx ++;
1641         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1642         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1643         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1644         values [MONO_METHOD_FLAGS] = mb->attrs;
1645         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1646         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1647         return_val_if_nok (error, FALSE);
1648         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1649         return_val_if_nok (error, FALSE);
1650
1651         table = &assembly->tables [MONO_TABLE_PARAM];
1652         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1653
1654         mono_image_add_decl_security (assembly, 
1655                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1656
1657         if (mb->pinfo) {
1658                 MonoDynamicTable *mtable;
1659                 guint32 *mvalues;
1660                 
1661                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1662                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1663                 
1664                 count = 0;
1665                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1666                         if (mono_array_get (mb->pinfo, gpointer, i))
1667                                 count++;
1668                 }
1669                 table->rows += count;
1670                 alloc_table (table, table->rows);
1671                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1672                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1673                         MonoReflectionParamBuilder *pb;
1674                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1675                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1676                                 values [MONO_PARAM_SEQUENCE] = i;
1677                                 if (pb->name != NULL) {
1678                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1679                                 } else {
1680                                         values [MONO_PARAM_NAME] = 0;
1681                                 }
1682                                 values += MONO_PARAM_SIZE;
1683                                 if (pb->marshal_info) {
1684                                         mtable->rows++;
1685                                         alloc_table (mtable, mtable->rows);
1686                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1687                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1688                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1689                                 }
1690                                 pb->table_idx = table->next_idx++;
1691                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1692                                         guint32 field_type = 0;
1693                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1694                                         mtable->rows ++;
1695                                         alloc_table (mtable, mtable->rows);
1696                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1697                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1698                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1699                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1700                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1701                                 }
1702                         }
1703                 }
1704         }
1705
1706         return TRUE;
1707 }
1708
1709 #ifndef DISABLE_REFLECTION_EMIT
1710 static gboolean
1711 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1712 {
1713         MONO_REQ_GC_UNSAFE_MODE;
1714
1715         mono_error_init (error);
1716         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1717
1718         rmb->ilgen = mb->ilgen;
1719         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1720         return_val_if_nok (error, FALSE);
1721         rmb->parameters = mb->parameters;
1722         rmb->generic_params = mb->generic_params;
1723         rmb->generic_container = mb->generic_container;
1724         rmb->opt_types = NULL;
1725         rmb->pinfo = mb->pinfo;
1726         rmb->attrs = mb->attrs;
1727         rmb->iattrs = mb->iattrs;
1728         rmb->call_conv = mb->call_conv;
1729         rmb->code = mb->code;
1730         rmb->type = mb->type;
1731         rmb->name = mb->name;
1732         rmb->table_idx = &mb->table_idx;
1733         rmb->init_locals = mb->init_locals;
1734         rmb->skip_visibility = FALSE;
1735         rmb->return_modreq = mb->return_modreq;
1736         rmb->return_modopt = mb->return_modopt;
1737         rmb->param_modreq = mb->param_modreq;
1738         rmb->param_modopt = mb->param_modopt;
1739         rmb->permissions = mb->permissions;
1740         rmb->mhandle = mb->mhandle;
1741         rmb->nrefs = 0;
1742         rmb->refs = NULL;
1743
1744         if (mb->dll) {
1745                 rmb->charset = mb->charset;
1746                 rmb->extra_flags = mb->extra_flags;
1747                 rmb->native_cc = mb->native_cc;
1748                 rmb->dllentry = mb->dllentry;
1749                 rmb->dll = mb->dll;
1750         }
1751
1752         return TRUE;
1753 }
1754
1755 static gboolean
1756 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1757 {
1758         MONO_REQ_GC_UNSAFE_MODE;
1759
1760         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1761
1762         mono_error_init (error);
1763
1764         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1765
1766         rmb->ilgen = mb->ilgen;
1767         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1768         return_val_if_nok (error, FALSE);
1769         rmb->parameters = mb->parameters;
1770         rmb->generic_params = NULL;
1771         rmb->generic_container = NULL;
1772         rmb->opt_types = NULL;
1773         rmb->pinfo = mb->pinfo;
1774         rmb->attrs = mb->attrs;
1775         rmb->iattrs = mb->iattrs;
1776         rmb->call_conv = mb->call_conv;
1777         rmb->code = NULL;
1778         rmb->type = mb->type;
1779         rmb->name = mono_string_new (mono_domain_get (), name);
1780         rmb->table_idx = &mb->table_idx;
1781         rmb->init_locals = mb->init_locals;
1782         rmb->skip_visibility = FALSE;
1783         rmb->return_modreq = NULL;
1784         rmb->return_modopt = NULL;
1785         rmb->param_modreq = mb->param_modreq;
1786         rmb->param_modopt = mb->param_modopt;
1787         rmb->permissions = mb->permissions;
1788         rmb->mhandle = mb->mhandle;
1789         rmb->nrefs = 0;
1790         rmb->refs = NULL;
1791
1792         return TRUE;
1793 }
1794
1795 static void
1796 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1797 {
1798         MONO_REQ_GC_UNSAFE_MODE;
1799
1800         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1801
1802         rmb->ilgen = mb->ilgen;
1803         rmb->rtype = mb->rtype;
1804         rmb->parameters = mb->parameters;
1805         rmb->generic_params = NULL;
1806         rmb->generic_container = NULL;
1807         rmb->opt_types = NULL;
1808         rmb->pinfo = NULL;
1809         rmb->attrs = mb->attrs;
1810         rmb->iattrs = 0;
1811         rmb->call_conv = mb->call_conv;
1812         rmb->code = NULL;
1813         rmb->type = (MonoObject *) mb->owner;
1814         rmb->name = mb->name;
1815         rmb->table_idx = NULL;
1816         rmb->init_locals = mb->init_locals;
1817         rmb->skip_visibility = mb->skip_visibility;
1818         rmb->return_modreq = NULL;
1819         rmb->return_modopt = NULL;
1820         rmb->param_modreq = NULL;
1821         rmb->param_modopt = NULL;
1822         rmb->permissions = NULL;
1823         rmb->mhandle = mb->mhandle;
1824         rmb->nrefs = 0;
1825         rmb->refs = NULL;
1826 }       
1827 #endif
1828
1829 static gboolean
1830 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1831 {
1832         MONO_REQ_GC_UNSAFE_MODE;
1833
1834         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1835         MonoDynamicTable *table;
1836         guint32 *values;
1837         guint32 tok;
1838         MonoReflectionMethod *m;
1839         int i;
1840
1841         mono_error_init (error);
1842
1843         if (!mb->override_methods)
1844                 return TRUE;
1845
1846         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1847                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1848
1849                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1850                 table->rows ++;
1851                 alloc_table (table, table->rows);
1852                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1853                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1854                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1855
1856                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1857                 return_val_if_nok (error, FALSE);
1858
1859                 switch (mono_metadata_token_table (tok)) {
1860                 case MONO_TABLE_MEMBERREF:
1861                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1862                         break;
1863                 case MONO_TABLE_METHOD:
1864                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1865                         break;
1866                 default:
1867                         g_assert_not_reached ();
1868                 }
1869                 values [MONO_METHODIMPL_DECLARATION] = tok;
1870         }
1871
1872         return TRUE;
1873 }
1874
1875 #ifndef DISABLE_REFLECTION_EMIT
1876 static gboolean
1877 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1878 {
1879         MONO_REQ_GC_UNSAFE_MODE;
1880
1881         MonoDynamicTable *table;
1882         guint32 *values;
1883         ReflectionMethodBuilder rmb;
1884         int i;
1885
1886         mono_error_init (error);
1887
1888         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1889             !mono_image_basic_method (&rmb, assembly, error))
1890                 return FALSE;
1891
1892         mb->table_idx = *rmb.table_idx;
1893
1894         if (mb->dll) { /* It's a P/Invoke method */
1895                 guint32 moduleref;
1896                 /* map CharSet values to on-disk values */
1897                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1898                 int extra_flags = mb->extra_flags;
1899                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1900                 table->rows ++;
1901                 alloc_table (table, table->rows);
1902                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1903                 
1904                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1905                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1906                 if (mb->dllentry)
1907                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1908                 else
1909                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1910                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1911                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1912                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1913                         table->rows ++;
1914                         alloc_table (table, table->rows);
1915                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1916                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1917                 }
1918         }
1919
1920         if (mb->generic_params) {
1921                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1922                 table->rows += mono_array_length (mb->generic_params);
1923                 alloc_table (table, table->rows);
1924                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1925                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1926
1927                         mono_image_get_generic_param_info (
1928                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1929                 }
1930         }
1931
1932         return TRUE;
1933 }
1934
1935 static gboolean
1936 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1937 {
1938         MONO_REQ_GC_UNSAFE_MODE;
1939
1940         ReflectionMethodBuilder rmb;
1941
1942         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1943                 return FALSE;
1944
1945         if (!mono_image_basic_method (&rmb, assembly, error))
1946                 return FALSE;
1947
1948         mb->table_idx = *rmb.table_idx;
1949
1950         return TRUE;
1951 }
1952 #endif
1953
1954 static char*
1955 type_get_fully_qualified_name (MonoType *type)
1956 {
1957         MONO_REQ_GC_NEUTRAL_MODE;
1958
1959         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1960 }
1961
1962 static char*
1963 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1964 {
1965         MONO_REQ_GC_UNSAFE_MODE;
1966
1967         MonoClass *klass;
1968         MonoAssembly *ta;
1969
1970         klass = mono_class_from_mono_type (type);
1971         if (!klass) 
1972                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1973         ta = klass->image->assembly;
1974         if (assembly_is_dynamic (ta) || (ta == ass)) {
1975                 if (klass->generic_class || klass->generic_container)
1976                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1977                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1978                 else
1979                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1980         }
1981
1982         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1983 }
1984
1985 #ifndef DISABLE_REFLECTION_EMIT
1986 /*field_image is the image to which the eventual custom mods have been encoded against*/
1987 static guint32
1988 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1989 {
1990         MONO_REQ_GC_NEUTRAL_MODE;
1991
1992         SigBuffer buf;
1993         guint32 idx, i, token;
1994
1995         if (!assembly->save)
1996                 return 0;
1997
1998         sigbuffer_init (&buf, 32);
1999         
2000         sigbuffer_add_value (&buf, 0x06);
2001         /* encode custom attributes before the type */
2002         if (type->num_mods) {
2003                 for (i = 0; i < type->num_mods; ++i) {
2004                         if (field_image) {
2005                                 MonoError error;
2006                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2007                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2008
2009                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2010                         } else {
2011                                 token = type->modifiers [i].token;
2012                         }
2013
2014                         if (type->modifiers [i].required)
2015                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2016                         else
2017                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2018
2019                         sigbuffer_add_value (&buf, token);
2020                 }
2021         }
2022         encode_type (assembly, type, &buf);
2023         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2024         sigbuffer_free (&buf);
2025         return idx;
2026 }
2027 #endif
2028
2029 static guint32
2030 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2031 {
2032         MONO_REQ_GC_UNSAFE_MODE;
2033
2034         MonoError error;
2035         SigBuffer buf;
2036         guint32 idx;
2037         guint32 typespec = 0;
2038         MonoType *type;
2039         MonoClass *klass;
2040
2041         init_type_builder_generics (fb->type);
2042
2043         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
2044         mono_error_raise_exception (&error); /* FIXME don't raise here */
2045         klass = mono_class_from_mono_type (type);
2046
2047         sigbuffer_init (&buf, 32);
2048         
2049         sigbuffer_add_value (&buf, 0x06);
2050         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, &error);
2051         if (!is_ok (&error))
2052                 goto fail;
2053         /* encode custom attributes before the type */
2054
2055         if (klass->generic_container)
2056                 typespec = create_typespec (assembly, type);
2057
2058         if (typespec) {
2059                 MonoGenericClass *gclass;
2060                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2061                 encode_generic_class (assembly, gclass, &buf);
2062         } else {
2063                 encode_type (assembly, type, &buf);
2064         }
2065         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2066         sigbuffer_free (&buf);
2067         return idx;
2068 fail:
2069         sigbuffer_free (&buf);
2070         mono_error_raise_exception (&error); /* FIXME don't raise here */
2071         g_assert_not_reached ();
2072 }
2073
2074 static guint32
2075 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2076 {
2077         MONO_REQ_GC_UNSAFE_MODE;
2078
2079         char blob_size [64];
2080         char *b = blob_size;
2081         char *box_val;
2082         char* buf;
2083         guint32 idx = 0, len = 0, dummy = 0;
2084
2085         buf = (char *)g_malloc (64);
2086         if (!val) {
2087                 *ret_type = MONO_TYPE_CLASS;
2088                 len = 4;
2089                 box_val = (char*)&dummy;
2090         } else {
2091                 box_val = ((char*)val) + sizeof (MonoObject);
2092                 *ret_type = val->vtable->klass->byval_arg.type;
2093         }
2094 handle_enum:
2095         switch (*ret_type) {
2096         case MONO_TYPE_BOOLEAN:
2097         case MONO_TYPE_U1:
2098         case MONO_TYPE_I1:
2099                 len = 1;
2100                 break;
2101         case MONO_TYPE_CHAR:
2102         case MONO_TYPE_U2:
2103         case MONO_TYPE_I2:
2104                 len = 2;
2105                 break;
2106         case MONO_TYPE_U4:
2107         case MONO_TYPE_I4:
2108         case MONO_TYPE_R4:
2109                 len = 4;
2110                 break;
2111         case MONO_TYPE_U8:
2112         case MONO_TYPE_I8:
2113                 len = 8;
2114                 break;
2115         case MONO_TYPE_R8:
2116                 len = 8;
2117                 break;
2118         case MONO_TYPE_VALUETYPE: {
2119                 MonoClass *klass = val->vtable->klass;
2120                 
2121                 if (klass->enumtype) {
2122                         *ret_type = mono_class_enum_basetype (klass)->type;
2123                         goto handle_enum;
2124                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2125                         len = 8;
2126                 } else 
2127                         g_error ("we can't encode valuetypes, we should have never reached this line");
2128                 break;
2129         }
2130         case MONO_TYPE_CLASS:
2131                 break;
2132         case MONO_TYPE_STRING: {
2133                 MonoString *str = (MonoString*)val;
2134                 /* there is no signature */
2135                 len = str->length * 2;
2136                 mono_metadata_encode_value (len, b, &b);
2137 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2138                 {
2139                         char *swapped = g_malloc (2 * mono_string_length (str));
2140                         const char *p = (const char*)mono_string_chars (str);
2141
2142                         swap_with_size (swapped, p, 2, mono_string_length (str));
2143                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2144                         g_free (swapped);
2145                 }
2146 #else
2147                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2148 #endif
2149
2150                 g_free (buf);
2151                 return idx;
2152         }
2153         case MONO_TYPE_GENERICINST:
2154                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2155                 goto handle_enum;
2156         default:
2157                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2158         }
2159
2160         /* there is no signature */
2161         mono_metadata_encode_value (len, b, &b);
2162 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2163         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2164         swap_with_size (blob_size, box_val, len, 1);
2165         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2166 #else
2167         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2168 #endif
2169
2170         g_free (buf);
2171         return idx;
2172 }
2173
2174 static guint32
2175 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2176 {
2177         MONO_REQ_GC_UNSAFE_MODE;
2178
2179         MonoError error;
2180         char *str;
2181         SigBuffer buf;
2182         guint32 idx, len;
2183
2184         sigbuffer_init (&buf, 32);
2185
2186         sigbuffer_add_value (&buf, minfo->type);
2187
2188         switch (minfo->type) {
2189         case MONO_NATIVE_BYVALTSTR:
2190         case MONO_NATIVE_BYVALARRAY:
2191                 sigbuffer_add_value (&buf, minfo->count);
2192                 break;
2193         case MONO_NATIVE_LPARRAY:
2194                 if (minfo->eltype || minfo->has_size) {
2195                         sigbuffer_add_value (&buf, minfo->eltype);
2196                         if (minfo->has_size) {
2197                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2198                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2199
2200                                 /* LAMESPEC: ElemMult is undocumented */
2201                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2202                         }
2203                 }
2204                 break;
2205         case MONO_NATIVE_SAFEARRAY:
2206                 if (minfo->eltype)
2207                         sigbuffer_add_value (&buf, minfo->eltype);
2208                 break;
2209         case MONO_NATIVE_CUSTOM:
2210                 if (minfo->guid) {
2211                         str = mono_string_to_utf8 (minfo->guid);
2212                         len = strlen (str);
2213                         sigbuffer_add_value (&buf, len);
2214                         sigbuffer_add_mem (&buf, str, len);
2215                         g_free (str);
2216                 } else {
2217                         sigbuffer_add_value (&buf, 0);
2218                 }
2219                 /* native type name */
2220                 sigbuffer_add_value (&buf, 0);
2221                 /* custom marshaler type name */
2222                 if (minfo->marshaltype || minfo->marshaltyperef) {
2223                         if (minfo->marshaltyperef) {
2224                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
2225                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
2226                                 str = type_get_fully_qualified_name (marshaltype);
2227                         } else
2228                                 str = mono_string_to_utf8 (minfo->marshaltype);
2229                         len = strlen (str);
2230                         sigbuffer_add_value (&buf, len);
2231                         sigbuffer_add_mem (&buf, str, len);
2232                         g_free (str);
2233                 } else {
2234                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2235                         sigbuffer_add_value (&buf, 0);
2236                 }
2237                 if (minfo->mcookie) {
2238                         str = mono_string_to_utf8 (minfo->mcookie);
2239                         len = strlen (str);
2240                         sigbuffer_add_value (&buf, len);
2241                         sigbuffer_add_mem (&buf, str, len);
2242                         g_free (str);
2243                 } else {
2244                         sigbuffer_add_value (&buf, 0);
2245                 }
2246                 break;
2247         default:
2248                 break;
2249         }
2250         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2251         sigbuffer_free (&buf);
2252         return idx;
2253 }
2254
2255 static void
2256 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2257 {
2258         MONO_REQ_GC_UNSAFE_MODE;
2259
2260         MonoDynamicTable *table;
2261         guint32 *values;
2262
2263         /* maybe this fixup should be done in the C# code */
2264         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2265                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2266         table = &assembly->tables [MONO_TABLE_FIELD];
2267         fb->table_idx = table->next_idx ++;
2268         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2269         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2270         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2271         values [MONO_FIELD_FLAGS] = fb->attrs;
2272         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2273
2274         if (fb->offset != -1) {
2275                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2276                 table->rows ++;
2277                 alloc_table (table, table->rows);
2278                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2279                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2280                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2281         }
2282         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2283                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2284                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2285                 table->rows ++;
2286                 alloc_table (table, table->rows);
2287                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2288                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2289                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2290                 values [MONO_CONSTANT_TYPE] = field_type;
2291                 values [MONO_CONSTANT_PADDING] = 0;
2292         }
2293         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2294                 guint32 rva_idx;
2295                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2296                 table->rows ++;
2297                 alloc_table (table, table->rows);
2298                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2299                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2300                 /*
2301                  * We store it in the code section because it's simpler for now.
2302                  */
2303                 if (fb->rva_data) {
2304                         if (mono_array_length (fb->rva_data) >= 10)
2305                                 stream_data_align (&assembly->code);
2306                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2307                 } else
2308                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2309                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2310         }
2311         if (fb->marshal_info) {
2312                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2313                 table->rows ++;
2314                 alloc_table (table, table->rows);
2315                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2316                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2317                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2318         }
2319 }
2320
2321 static guint32
2322 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2323 {
2324         MONO_REQ_GC_UNSAFE_MODE;
2325
2326         MonoError error;
2327         SigBuffer buf;
2328         guint32 nparams = 0;
2329         MonoReflectionMethodBuilder *mb = fb->get_method;
2330         MonoReflectionMethodBuilder *smb = fb->set_method;
2331         guint32 idx, i;
2332
2333         if (mb && mb->parameters)
2334                 nparams = mono_array_length (mb->parameters);
2335         if (!mb && smb && smb->parameters)
2336                 nparams = mono_array_length (smb->parameters) - 1;
2337         sigbuffer_init (&buf, 32);
2338         if (fb->call_conv & 0x20)
2339                 sigbuffer_add_byte (&buf, 0x28);
2340         else
2341                 sigbuffer_add_byte (&buf, 0x08);
2342         sigbuffer_add_value (&buf, nparams);
2343         if (mb) {
2344                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, &error);
2345                 if (!is_ok (&error))
2346                         goto fail;
2347                 for (i = 0; i < nparams; ++i) {
2348                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2349                         encode_reflection_type (assembly, pt, &buf, &error);
2350                         if (!is_ok (&error))
2351                                 goto fail;
2352                 }
2353         } else if (smb && smb->parameters) {
2354                 /* the property type is the last param */
2355                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, &error);
2356                 if (!is_ok (&error))
2357                         goto fail;
2358
2359                 for (i = 0; i < nparams; ++i) {
2360                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2361                         encode_reflection_type (assembly, pt, &buf, &error);
2362                         if (!is_ok (&error))
2363                                 goto fail;
2364                 }
2365         } else {
2366                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, &error);
2367                 if (!is_ok (&error))
2368                         goto fail;
2369         }
2370
2371         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2372         sigbuffer_free (&buf);
2373         return idx;
2374 fail:
2375         sigbuffer_free (&buf);
2376         mono_error_raise_exception (&error); /* FIXME don't raise here */
2377         g_assert_not_reached ();
2378 }
2379
2380 static void
2381 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2382 {
2383         MONO_REQ_GC_UNSAFE_MODE;
2384
2385         MonoDynamicTable *table;
2386         guint32 *values;
2387         guint num_methods = 0;
2388         guint32 semaidx;
2389
2390         /* 
2391          * we need to set things in the following tables:
2392          * PROPERTYMAP (info already filled in _get_type_info ())
2393          * PROPERTY    (rows already preallocated in _get_type_info ())
2394          * METHOD      (method info already done with the generic method code)
2395          * METHODSEMANTICS
2396          * CONSTANT
2397          */
2398         table = &assembly->tables [MONO_TABLE_PROPERTY];
2399         pb->table_idx = table->next_idx ++;
2400         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2401         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2402         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2403         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2404
2405         /* FIXME: we still don't handle 'other' methods */
2406         if (pb->get_method) num_methods ++;
2407         if (pb->set_method) num_methods ++;
2408
2409         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2410         table->rows += num_methods;
2411         alloc_table (table, table->rows);
2412
2413         if (pb->get_method) {
2414                 semaidx = table->next_idx ++;
2415                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2416                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2417                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2418                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2419         }
2420         if (pb->set_method) {
2421                 semaidx = table->next_idx ++;
2422                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2423                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2424                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2425                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2426         }
2427         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2428                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2429                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2430                 table->rows ++;
2431                 alloc_table (table, table->rows);
2432                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2433                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2434                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2435                 values [MONO_CONSTANT_TYPE] = field_type;
2436                 values [MONO_CONSTANT_PADDING] = 0;
2437         }
2438 }
2439
2440 static void
2441 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2442 {
2443         MONO_REQ_GC_UNSAFE_MODE;
2444
2445         MonoError error;
2446         MonoDynamicTable *table;
2447         guint32 *values;
2448         guint num_methods = 0;
2449         guint32 semaidx;
2450
2451         /* 
2452          * we need to set things in the following tables:
2453          * EVENTMAP (info already filled in _get_type_info ())
2454          * EVENT    (rows already preallocated in _get_type_info ())
2455          * METHOD      (method info already done with the generic method code)
2456          * METHODSEMANTICS
2457          */
2458         table = &assembly->tables [MONO_TABLE_EVENT];
2459         eb->table_idx = table->next_idx ++;
2460         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2461         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2462         values [MONO_EVENT_FLAGS] = eb->attrs;
2463         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, &error);
2464         mono_error_raise_exception (&error); /* FIXME don't raise here */
2465         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2466
2467         /*
2468          * FIXME: we still don't handle 'other' methods 
2469          */
2470         if (eb->add_method) num_methods ++;
2471         if (eb->remove_method) num_methods ++;
2472         if (eb->raise_method) num_methods ++;
2473
2474         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2475         table->rows += num_methods;
2476         alloc_table (table, table->rows);
2477
2478         if (eb->add_method) {
2479                 semaidx = table->next_idx ++;
2480                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2481                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2482                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2483                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2484         }
2485         if (eb->remove_method) {
2486                 semaidx = table->next_idx ++;
2487                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2488                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2489                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2490                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2491         }
2492         if (eb->raise_method) {
2493                 semaidx = table->next_idx ++;
2494                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2495                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2496                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2497                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2498         }
2499 }
2500
2501 static void
2502 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2503 {
2504         MONO_REQ_GC_UNSAFE_MODE;
2505
2506         MonoError error;
2507         MonoDynamicTable *table;
2508         guint32 num_constraints, i;
2509         guint32 *values;
2510         guint32 table_idx;
2511
2512         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2513         num_constraints = gparam->iface_constraints ?
2514                 mono_array_length (gparam->iface_constraints) : 0;
2515         table->rows += num_constraints;
2516         if (gparam->base_type)
2517                 table->rows++;
2518         alloc_table (table, table->rows);
2519
2520         if (gparam->base_type) {
2521                 table_idx = table->next_idx ++;
2522                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2523
2524                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, &error);
2525                 mono_error_raise_exception (&error); /* FIXME don't raise here */
2526                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2527                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2528         }
2529
2530         for (i = 0; i < num_constraints; i++) {
2531                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2532                         gparam->iface_constraints, gpointer, i);
2533
2534                 table_idx = table->next_idx ++;
2535                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2536
2537                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, &error);
2538                 mono_error_raise_exception (&error); /* FIXME don't raise here */
2539
2540                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2541                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2542         }
2543 }
2544
2545 static void
2546 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2547 {
2548         MONO_REQ_GC_UNSAFE_MODE;
2549
2550         GenericParamTableEntry *entry;
2551
2552         /*
2553          * The GenericParam table must be sorted according to the `owner' field.
2554          * We need to do this sorting prior to writing the GenericParamConstraint
2555          * table, since we have to use the final GenericParam table indices there
2556          * and they must also be sorted.
2557          */
2558
2559         entry = g_new0 (GenericParamTableEntry, 1);
2560         entry->owner = owner;
2561         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2562         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2563         entry->gparam = gparam;
2564         
2565         g_ptr_array_add (assembly->gen_params, entry);
2566 }
2567
2568 static gboolean
2569 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2570 {
2571         MONO_REQ_GC_UNSAFE_MODE;
2572
2573         MonoDynamicTable *table;
2574         MonoGenericParam *param;
2575         guint32 *values;
2576         guint32 table_idx;
2577
2578         mono_error_init (error);
2579
2580         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2581         table_idx = table->next_idx ++;
2582         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2583
2584         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2585         return_val_if_nok (error, FALSE);
2586
2587         param = gparam_type->data.generic_param;
2588
2589         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2590         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2591         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2592         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2593
2594         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2595                 return FALSE;
2596
2597         encode_constraints (entry->gparam, table_idx, assembly);
2598
2599         return TRUE;
2600 }
2601
2602 static guint32
2603 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2604 {
2605         MONO_REQ_GC_UNSAFE_MODE;
2606
2607         MonoDynamicTable *table;
2608         guint32 token;
2609         guint32 *values;
2610         guint32 cols [MONO_ASSEMBLY_SIZE];
2611         const char *pubkey;
2612         guint32 publen;
2613
2614         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2615                 return token;
2616
2617         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2618                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2619                 token = table->next_idx ++;
2620                 table->rows ++;
2621                 alloc_table (table, table->rows);
2622                 values = table->values + token * MONO_MODULEREF_SIZE;
2623                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2624
2625                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2626                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2627                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2628
2629                 return token;
2630         }
2631         
2632         if (assembly_is_dynamic (image->assembly))
2633                 /* FIXME: */
2634                 memset (cols, 0, sizeof (cols));
2635         else {
2636                 /* image->assembly->image is the manifest module */
2637                 image = image->assembly->image;
2638                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2639         }
2640
2641         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2642         token = table->next_idx ++;
2643         table->rows ++;
2644         alloc_table (table, table->rows);
2645         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2646         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2647         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2648         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2649         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2650         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2651         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2652         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2653         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2654
2655         if (strcmp ("", image->assembly->aname.culture)) {
2656                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2657                                 image->assembly->aname.culture);
2658         }
2659
2660         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2661                 guchar pubtoken [9];
2662                 pubtoken [0] = 8;
2663                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2664                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2665         } else {
2666                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2667         }
2668         token <<= MONO_RESOLUTION_SCOPE_BITS;
2669         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2670         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2671         return token;
2672 }
2673
2674 static guint32
2675 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2676 {
2677         MONO_REQ_GC_NEUTRAL_MODE;
2678
2679         MonoDynamicTable *table;
2680         guint32 *values;
2681         guint32 token;
2682         SigBuffer buf;
2683
2684         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2685                 return token;
2686
2687         sigbuffer_init (&buf, 32);
2688         switch (type->type) {
2689         case MONO_TYPE_FNPTR:
2690         case MONO_TYPE_PTR:
2691         case MONO_TYPE_SZARRAY:
2692         case MONO_TYPE_ARRAY:
2693         case MONO_TYPE_VAR:
2694         case MONO_TYPE_MVAR:
2695         case MONO_TYPE_GENERICINST:
2696                 encode_type (assembly, type, &buf);
2697                 break;
2698         case MONO_TYPE_CLASS:
2699         case MONO_TYPE_VALUETYPE: {
2700                 MonoClass *k = mono_class_from_mono_type (type);
2701                 if (!k || !k->generic_container) {
2702                         sigbuffer_free (&buf);
2703                         return 0;
2704                 }
2705                 encode_type (assembly, type, &buf);
2706                 break;
2707         }
2708         default:
2709                 sigbuffer_free (&buf);
2710                 return 0;
2711         }
2712
2713         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2714         if (assembly->save) {
2715                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2716                 alloc_table (table, table->rows + 1);
2717                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2718                 values [MONO_TYPESPEC_SIGNATURE] = token;
2719         }
2720         sigbuffer_free (&buf);
2721
2722         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2723         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2724         table->next_idx ++;
2725         return token;
2726 }
2727
2728 static guint32
2729 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2730 {
2731         MONO_REQ_GC_UNSAFE_MODE;
2732
2733         MonoDynamicTable *table;
2734         guint32 *values;
2735         guint32 token, scope, enclosing;
2736         MonoClass *klass;
2737
2738         /* if the type requires a typespec, we must try that first*/
2739         if (try_typespec && (token = create_typespec (assembly, type)))
2740                 return token;
2741         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2742         if (token)
2743                 return token;
2744         klass = mono_class_from_mono_type (type);
2745         if (!klass)
2746                 klass = mono_class_from_mono_type (type);
2747
2748         /*
2749          * If it's in the same module and not a generic type parameter:
2750          */
2751         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2752                         (type->type != MONO_TYPE_MVAR)) {
2753                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2754                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2755                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2756                 return token;
2757         }
2758
2759         if (klass->nested_in) {
2760                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2761                 /* get the typeref idx of the enclosing type */
2762                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2763                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2764         } else {
2765                 scope = resolution_scope_from_image (assembly, klass->image);
2766         }
2767         table = &assembly->tables [MONO_TABLE_TYPEREF];
2768         if (assembly->save) {
2769                 alloc_table (table, table->rows + 1);
2770                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2771                 values [MONO_TYPEREF_SCOPE] = scope;
2772                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2773                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2774         }
2775         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2776         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2777         table->next_idx ++;
2778         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2779         return token;
2780 }
2781
2782 /*
2783  * Despite the name, we handle also TypeSpec (with the above helper).
2784  */
2785 static guint32
2786 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2787 {
2788         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2789 }
2790
2791 #ifndef DISABLE_REFLECTION_EMIT
2792 static guint32
2793 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2794 {
2795         MONO_REQ_GC_NEUTRAL_MODE;
2796
2797         MonoDynamicTable *table;
2798         guint32 *values;
2799         guint32 token, pclass;
2800
2801         switch (parent & MONO_TYPEDEFORREF_MASK) {
2802         case MONO_TYPEDEFORREF_TYPEREF:
2803                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2804                 break;
2805         case MONO_TYPEDEFORREF_TYPESPEC:
2806                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2807                 break;
2808         case MONO_TYPEDEFORREF_TYPEDEF:
2809                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2810                 break;
2811         default:
2812                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2813                 return 0;
2814         }
2815         /* extract the index */
2816         parent >>= MONO_TYPEDEFORREF_BITS;
2817
2818         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2819
2820         if (assembly->save) {
2821                 alloc_table (table, table->rows + 1);
2822                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2823                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2824                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2825                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2826         }
2827
2828         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2829         table->next_idx ++;
2830
2831         return token;
2832 }
2833
2834 /*
2835  * Insert a memberef row into the metadata: the token that point to the memberref
2836  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2837  * mono_image_get_fieldref_token()).
2838  * The sig param is an index to an already built signature.
2839  */
2840 static guint32
2841 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2842 {
2843         MONO_REQ_GC_NEUTRAL_MODE;
2844
2845         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2846         return mono_image_add_memberef_row (assembly, parent, name, sig);
2847 }
2848
2849
2850 static guint32
2851 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2852 {
2853         MONO_REQ_GC_NEUTRAL_MODE;
2854
2855         guint32 token;
2856         MonoMethodSignature *sig;
2857         
2858         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2859
2860         if (create_typespec) {
2861                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2862                 if (token)
2863                         return token;
2864         } 
2865
2866         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2867         if (token && !create_typespec)
2868                 return token;
2869
2870         g_assert (!method->is_inflated);
2871         if (!token) {
2872                 /*
2873                  * A methodref signature can't contain an unmanaged calling convention.
2874                  */
2875                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2876                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2877                         sig->call_convention = MONO_CALL_DEFAULT;
2878                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2879                         method->name,  method_encode_signature (assembly, sig));
2880                 g_free (sig);
2881                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2882         }
2883
2884         if (create_typespec) {
2885                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2886                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2887                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2888
2889                 if (assembly->save) {
2890                         guint32 *values;
2891
2892                         alloc_table (table, table->rows + 1);
2893                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2894                         values [MONO_METHODSPEC_METHOD] = token;
2895                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2896                 }
2897
2898                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2899                 table->next_idx ++;
2900                 /*methodspec and memberef tokens are diferent, */
2901                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2902                 return token;
2903         }
2904         return token;
2905 }
2906
2907 static guint32
2908 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2909 {
2910         guint32 token, parent, sig;
2911         ReflectionMethodBuilder rmb;
2912         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2913         
2914         mono_error_init (error);
2915         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2916         if (token)
2917                 return token;
2918
2919         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2920                 return 0;
2921
2922         /*
2923          * A methodref signature can't contain an unmanaged calling convention.
2924          * Since some flags are encoded as part of call_conv, we need to check against it.
2925         */
2926         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2927                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2928
2929         sig = method_builder_encode_signature (assembly, &rmb, error);
2930         return_val_if_nok (error, 0);
2931
2932         if (tb->generic_params)
2933                 parent = create_generic_typespec (assembly, tb);
2934         else {
2935                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2936                 return_val_if_nok (error, 0);
2937
2938                 parent = mono_image_typedef_or_ref (assembly, t);
2939         }
2940
2941         char *name = mono_string_to_utf8 (method->name);
2942
2943         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2944         g_free (name);
2945
2946         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2947
2948         return token;
2949 }
2950
2951 static guint32
2952 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2953                                      const gchar *name, guint32 sig)
2954 {
2955         MonoDynamicTable *table;
2956         guint32 token;
2957         guint32 *values;
2958         
2959         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2960
2961         if (assembly->save) {
2962                 alloc_table (table, table->rows + 1);
2963                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2964                 values [MONO_MEMBERREF_CLASS] = original;
2965                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2966                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2967         }
2968
2969         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2970         table->next_idx ++;
2971
2972         return token;
2973 }
2974
2975 static guint32
2976 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2977 {
2978         SigBuffer buf;
2979         int i;
2980         guint32 nparams = mono_array_length (mb->generic_params);
2981         guint32 idx;
2982
2983         if (!assembly->save)
2984                 return 0;
2985
2986         sigbuffer_init (&buf, 32);
2987
2988         sigbuffer_add_value (&buf, 0xa);
2989         sigbuffer_add_value (&buf, nparams);
2990
2991         for (i = 0; i < nparams; i++) {
2992                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2993                 sigbuffer_add_value (&buf, i);
2994         }
2995
2996         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2997         sigbuffer_free (&buf);
2998         return idx;
2999 }
3000
3001 static guint32
3002 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3003 {
3004         MonoDynamicTable *table;
3005         guint32 *values;
3006         guint32 token, mtoken = 0;
3007
3008         mono_error_init (error);
3009         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3010         if (token)
3011                 return token;
3012
3013         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3014
3015         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3016         if (!mono_error_ok (error))
3017                 return 0;
3018
3019         switch (mono_metadata_token_table (mtoken)) {
3020         case MONO_TABLE_MEMBERREF:
3021                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3022                 break;
3023         case MONO_TABLE_METHOD:
3024                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3025                 break;
3026         default:
3027                 g_assert_not_reached ();
3028         }
3029
3030         if (assembly->save) {
3031                 alloc_table (table, table->rows + 1);
3032                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3033                 values [MONO_METHODSPEC_METHOD] = mtoken;
3034                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3035         }
3036
3037         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3038         table->next_idx ++;
3039
3040         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3041         return token;
3042 }
3043
3044 static guint32
3045 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3046 {
3047         guint32 token;
3048
3049         mono_error_init (error);
3050
3051         if (mb->generic_params && create_methodspec) 
3052                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3053
3054         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3055         if (token)
3056                 return token;
3057
3058         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3059         if (!mono_error_ok (error))
3060                 return 0;
3061         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3062         return token;
3063 }
3064
3065 static guint32
3066 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3067 {
3068         guint32 token, parent, sig;
3069         ReflectionMethodBuilder rmb;
3070         char *name;
3071         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3072         
3073         mono_error_init (error);
3074         
3075         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3076         if (token)
3077                 return token;
3078
3079         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3080                 return 0;
3081
3082         if (tb->generic_params)
3083                 parent = create_generic_typespec (assembly, tb);
3084         else {
3085                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3086                 return_val_if_nok (error, 0);
3087                 parent = mono_image_typedef_or_ref (assembly, type);
3088         }
3089         
3090         name = mono_string_to_utf8 (rmb.name);
3091         sig = method_builder_encode_signature (assembly, &rmb, error);
3092         return_val_if_nok (error, 0);
3093
3094         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3095
3096         g_free (name);
3097         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3098         return token;
3099 }
3100 #endif
3101
3102 static gboolean
3103 is_field_on_inst (MonoClassField *field)
3104 {
3105         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3106 }
3107
3108 /*
3109  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3110  */
3111 static MonoType*
3112 get_field_on_inst_generic_type (MonoClassField *field)
3113 {
3114         MonoClass *klass, *gtd;
3115         MonoDynamicGenericClass *dgclass;
3116         int field_index;
3117
3118         g_assert (is_field_on_inst (field));
3119
3120         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3121
3122         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3123                 field_index = field - dgclass->fields;
3124                 return dgclass->field_generic_types [field_index];              
3125         }
3126
3127         klass = field->parent;
3128         gtd = klass->generic_class->container_class;
3129
3130         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3131                 field_index = field - klass->fields;
3132                 return gtd->fields [field_index].type;
3133         }
3134
3135         g_assert_not_reached ();
3136         return 0;
3137 }
3138
3139 #ifndef DISABLE_REFLECTION_EMIT
3140 static guint32
3141 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3142 {
3143         MonoType *type;
3144         guint32 token;
3145
3146         g_assert (field);
3147         g_assert (field->parent);
3148
3149         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3150         if (token)
3151                 return token;
3152
3153         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3154                 int index = field - field->parent->fields;
3155                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3156         } else {
3157                 if (is_field_on_inst (field))
3158                         type = get_field_on_inst_generic_type (field);
3159                 else
3160                         type = mono_field_get_type (field);
3161         }
3162         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3163                                                                                         mono_field_get_name (field),
3164                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3165         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3166         return token;
3167 }
3168
3169 static guint32
3170 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3171 {
3172         MonoError error;
3173         guint32 token;
3174         MonoClass *klass;
3175         MonoGenericClass *gclass;
3176         MonoType *type;
3177         char *name;
3178
3179         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3180         if (token)
3181                 return token;
3182         if (is_sre_field_builder (mono_object_class (f->fb))) {
3183                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3184                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
3185                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3186                 klass = mono_class_from_mono_type (type);
3187                 gclass = type->data.generic_class;
3188                 g_assert (gclass->is_dynamic);
3189
3190                 name = mono_string_to_utf8 (fb->name);
3191                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
3192                                                                                                 field_encode_signature (assembly, fb));
3193                 g_free (name);          
3194         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3195                 guint32 sig;
3196                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3197
3198                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
3199                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3200                 klass = mono_class_from_mono_type (type);
3201
3202                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3203                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3204         } else {
3205                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3206                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3207         }
3208
3209         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3210         return token;
3211 }
3212
3213 static guint32
3214 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3215 {
3216         guint32 sig, token;
3217         MonoClass *klass;
3218         MonoGenericClass *gclass;
3219         MonoType *type;
3220
3221         mono_error_init (error);
3222
3223         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3224
3225         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3226         if (token)
3227                 return token;
3228
3229         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3230                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3231                 ReflectionMethodBuilder rmb;
3232                 char *name;
3233
3234                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3235                 return_val_if_nok (error, 0);
3236                 klass = mono_class_from_mono_type (type);
3237
3238                 gclass = type->data.generic_class;
3239                 g_assert (gclass->is_dynamic);
3240
3241                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3242                         return 0;
3243
3244                 sig = method_builder_encode_signature (assembly, &rmb, error);
3245                 return_val_if_nok (error, 0);
3246
3247                 name = mono_string_to_utf8 (rmb.name);
3248
3249                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3250                 g_free (name);
3251         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3252                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3253
3254                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3255                 return_val_if_nok (error, 0);
3256                 klass = mono_class_from_mono_type (type);
3257
3258                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3259                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3260         } else {
3261                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3262                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3263         }
3264
3265
3266         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3267         return token;
3268 }
3269
3270 static MonoMethod*
3271 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3272 {
3273         MonoClass *klass;
3274         MonoGenericContext tmp_context;
3275         MonoType **type_argv;
3276         MonoGenericInst *ginst;
3277         MonoMethod *method, *inflated;
3278         int count, i;
3279
3280         mono_error_init (error);
3281
3282         init_type_builder_generics ((MonoObject*)m->inst);
3283
3284         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3285         return_val_if_nok (error, NULL);
3286
3287         klass = method->klass;
3288
3289         if (m->method_args == NULL)
3290                 return method;
3291
3292         if (method->is_inflated)
3293                 method = ((MonoMethodInflated *) method)->declaring;
3294
3295         count = mono_array_length (m->method_args);
3296
3297         type_argv = g_new0 (MonoType *, count);
3298         for (i = 0; i < count; i++) {
3299                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3300                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3301                 return_val_if_nok (error, NULL);
3302         }
3303         ginst = mono_metadata_get_generic_inst (count, type_argv);
3304         g_free (type_argv);
3305
3306         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3307         tmp_context.method_inst = ginst;
3308
3309         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3310         mono_error_assert_ok (error);
3311         return inflated;
3312 }
3313
3314 static guint32
3315 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3316 {
3317         guint32 sig, token = 0;
3318         MonoType *type;
3319         MonoClass *klass;
3320
3321         mono_error_init (error);
3322
3323         if (m->method_args) {
3324                 MonoMethod *inflated;
3325
3326                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3327                 return_val_if_nok (error, 0);
3328
3329                 if (create_methodspec)
3330                         token = mono_image_get_methodspec_token (assembly, inflated);
3331                 else
3332                         token = mono_image_get_inflated_method_token (assembly, inflated);
3333                 return token;
3334         }
3335
3336         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3337         if (token)
3338                 return token;
3339
3340         if (is_sre_method_builder (mono_object_class (m->mb))) {
3341                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3342                 MonoGenericClass *gclass;
3343                 ReflectionMethodBuilder rmb;
3344                 char *name;
3345
3346                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3347                 return_val_if_nok (error, 0);
3348                 klass = mono_class_from_mono_type (type);
3349                 gclass = type->data.generic_class;
3350                 g_assert (gclass->is_dynamic);
3351
3352                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3353                         return 0;
3354
3355                 sig = method_builder_encode_signature (assembly, &rmb, error);
3356                 return_val_if_nok (error, 0);
3357
3358                 name = mono_string_to_utf8 (rmb.name);
3359
3360                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3361                 g_free (name);          
3362         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3363                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3364
3365                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3366                 return_val_if_nok (error, 0);
3367                 klass = mono_class_from_mono_type (type);
3368
3369                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3370                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3371         } else {
3372                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3373                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3374         }
3375
3376         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3377         return token;
3378 }
3379
3380 static guint32
3381 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3382 {
3383         SigBuffer buf;
3384         int i;
3385         guint32 nparams = context->method_inst->type_argc;
3386         guint32 idx;
3387
3388         if (!assembly->save)
3389                 return 0;
3390
3391         sigbuffer_init (&buf, 32);
3392         /*
3393          * FIXME: vararg, explicit_this, differenc call_conv values...
3394          */
3395         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3396         sigbuffer_add_value (&buf, nparams);
3397
3398         for (i = 0; i < nparams; i++)
3399                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3400
3401         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3402         sigbuffer_free (&buf);
3403         return idx;
3404 }
3405
3406 static guint32
3407 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3408 {
3409         MonoDynamicTable *table;
3410         guint32 *values;
3411         guint32 token, mtoken = 0, sig;
3412         MonoMethodInflated *imethod;
3413         MonoMethod *declaring;
3414
3415         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3416
3417         g_assert (method->is_inflated);
3418         imethod = (MonoMethodInflated *) method;
3419         declaring = imethod->declaring;
3420
3421         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3422         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3423
3424         if (!mono_method_signature (declaring)->generic_param_count)
3425                 return mtoken;
3426
3427         switch (mono_metadata_token_table (mtoken)) {
3428         case MONO_TABLE_MEMBERREF:
3429                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3430                 break;
3431         case MONO_TABLE_METHOD:
3432                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3433                 break;
3434         default:
3435                 g_assert_not_reached ();
3436         }
3437
3438         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3439
3440         if (assembly->save) {
3441                 alloc_table (table, table->rows + 1);
3442                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3443                 values [MONO_METHODSPEC_METHOD] = mtoken;
3444                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3445         }
3446
3447         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3448         table->next_idx ++;
3449
3450         return token;
3451 }
3452
3453 static guint32
3454 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3455 {
3456         MonoMethodInflated *imethod;
3457         guint32 token;
3458         
3459         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3460         if (token)
3461                 return token;
3462
3463         g_assert (method->is_inflated);
3464         imethod = (MonoMethodInflated *) method;
3465
3466         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3467                 token = method_encode_methodspec (assembly, method);
3468         } else {
3469                 guint32 sig = method_encode_signature (
3470                         assembly, mono_method_signature (imethod->declaring));
3471                 token = mono_image_get_memberref_token (
3472                         assembly, &method->klass->byval_arg, method->name, sig);
3473         }
3474
3475         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3476         return token;
3477 }
3478
3479 static guint32
3480 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3481 {
3482         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3483         guint32 sig, token;
3484
3485         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3486         token = mono_image_get_memberref_token (
3487                 assembly, &m->klass->byval_arg, m->name, sig);
3488
3489         return token;
3490 }
3491
3492 static guint32
3493 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3494 {
3495         MonoError error;
3496         MonoDynamicTable *table;
3497         MonoClass *klass;
3498         MonoType *type;
3499         guint32 *values;
3500         guint32 token;
3501         SigBuffer buf;
3502         int count, i;
3503
3504         /*
3505          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3506          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3507          * Because of this, we must not insert it into the `typeref' hash table.
3508          */
3509         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
3510         mono_error_raise_exception (&error); /* FIXME don't raise here */
3511         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3512         if (token)
3513                 return token;
3514
3515         sigbuffer_init (&buf, 32);
3516
3517         g_assert (tb->generic_params);
3518         klass = mono_class_from_mono_type (type);
3519
3520         if (tb->generic_container)
3521                 mono_reflection_create_generic_class (tb);
3522
3523         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3524         g_assert (klass->generic_container);
3525         sigbuffer_add_value (&buf, klass->byval_arg.type);
3526         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3527
3528         count = mono_array_length (tb->generic_params);
3529         sigbuffer_add_value (&buf, count);
3530         for (i = 0; i < count; i++) {
3531                 MonoReflectionGenericParam *gparam;
3532
3533                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3534                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
3535                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3536
3537                 encode_type (assembly, gparam_type, &buf);
3538         }
3539
3540         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3541
3542         if (assembly->save) {
3543                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3544                 alloc_table (table, table->rows + 1);
3545                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3546                 values [MONO_TYPESPEC_SIGNATURE] = token;
3547         }
3548         sigbuffer_free (&buf);
3549
3550         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3551         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3552         table->next_idx ++;
3553         return token;
3554 }
3555
3556 /*
3557  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3558  */
3559 static MonoType*
3560 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3561 {
3562         MonoError error;
3563         int i, count, len, pos;
3564         MonoType *t;
3565
3566         count = 0;
3567         if (modreq)
3568                 count += mono_array_length (modreq);
3569         if (modopt)
3570                 count += mono_array_length (modopt);
3571
3572         if (count == 0)
3573                 return mono_metadata_type_dup (NULL, type);
3574
3575         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3576         t = (MonoType *)g_malloc (len);
3577         memcpy (t, type, MONO_SIZEOF_TYPE);
3578
3579         t->num_mods = count;
3580         pos = 0;
3581         if (modreq) {
3582                 for (i = 0; i < mono_array_length (modreq); ++i) {
3583                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, &error);
3584                         mono_error_raise_exception (&error); /* FIXME don't raise here */
3585                         t->modifiers [pos].required = 1;
3586                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3587                         pos ++;
3588                 }
3589         }
3590         if (modopt) {
3591                 for (i = 0; i < mono_array_length (modopt); ++i) {
3592                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, &error);
3593                         mono_error_raise_exception (&error); /* FIXME don't raise here */
3594                         t->modifiers [pos].required = 0;
3595                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3596                         pos ++;
3597                 }
3598         }
3599
3600         return t;
3601 }
3602
3603 static void
3604 init_type_builder_generics (MonoObject *type)
3605 {
3606         MonoReflectionTypeBuilder *tb;
3607
3608         if (!is_sre_type_builder(mono_object_class (type)))
3609                 return;
3610         tb = (MonoReflectionTypeBuilder *)type;
3611
3612         if (tb && tb->generic_container)
3613                 mono_reflection_create_generic_class (tb);
3614 }
3615
3616 static guint32
3617 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3618 {
3619         MonoError error;
3620         MonoDynamicTable *table;
3621         MonoType *custom = NULL, *type;
3622         guint32 *values;
3623         guint32 token, pclass, parent, sig;
3624         gchar *name;
3625
3626         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3627         if (token)
3628                 return token;
3629
3630         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, &error);
3631         mono_error_raise_exception (&error); /* FIXME don't raise here */
3632         /* FIXME: is this call necessary? */
3633         mono_class_from_mono_type (typeb);
3634         name = mono_string_to_utf8 (fb->name);
3635
3636         /*FIXME this is one more layer of ugliness due how types are created.*/
3637         init_type_builder_generics (fb->type);
3638
3639         /* fb->type does not include the custom modifiers */
3640         /* FIXME: We should do this in one place when a fieldbuilder is created */
3641         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
3642         mono_error_raise_exception (&error); /* FIXME don't raise here */
3643
3644         if (fb->modreq || fb->modopt)
3645                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3646
3647         sig = fieldref_encode_signature (assembly, NULL, type);
3648         g_free (custom);
3649
3650         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3651         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3652         
3653         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3654         parent >>= MONO_TYPEDEFORREF_BITS;
3655
3656         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3657
3658         if (assembly->save) {
3659                 alloc_table (table, table->rows + 1);
3660                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3661                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3662                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3663                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3664         }
3665
3666         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3667         table->next_idx ++;
3668         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3669         g_free (name);
3670         return token;
3671 }
3672
3673 static guint32
3674 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3675 {
3676         MonoError error;
3677         SigBuffer buf;
3678         guint32 nargs;
3679         guint32 i, idx;
3680
3681         if (!assembly->save)
3682                 return 0;
3683
3684         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3685         g_assert (helper->type == 2);
3686
3687         if (helper->arguments)
3688                 nargs = mono_array_length (helper->arguments);
3689         else
3690                 nargs = 0;
3691
3692         sigbuffer_init (&buf, 32);
3693
3694         /* Encode calling convention */
3695         /* Change Any to Standard */
3696         if ((helper->call_conv & 0x03) == 0x03)
3697                 helper->call_conv = 0x01;
3698         /* explicit_this implies has_this */
3699         if (helper->call_conv & 0x40)
3700                 helper->call_conv &= 0x20;
3701
3702         if (helper->call_conv == 0) { /* Unmanaged */
3703                 idx = helper->unmanaged_call_conv - 1;
3704         } else {
3705                 /* Managed */
3706                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3707                 if (helper->call_conv & 0x02) /* varargs */
3708                         idx += 0x05;
3709         }
3710
3711         sigbuffer_add_byte (&buf, idx);
3712         sigbuffer_add_value (&buf, nargs);
3713         encode_reflection_type (assembly, helper->return_type, &buf, &error);
3714         if (!is_ok (&error))
3715                 goto fail;
3716         for (i = 0; i < nargs; ++i) {
3717                 MonoArray *modreqs = NULL;
3718                 MonoArray *modopts = NULL;
3719                 MonoReflectionType *pt;
3720
3721                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3722                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3723                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3724                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3725
3726                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, &error);
3727                 if (!is_ok (&error))
3728                         goto fail;
3729                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3730                 encode_reflection_type (assembly, pt, &buf, &error);
3731                 if (!is_ok (&error))
3732                         goto fail;
3733         }
3734         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3735         sigbuffer_free (&buf);
3736
3737         return idx;
3738 fail:
3739         sigbuffer_free (&buf);
3740         mono_error_raise_exception (&error); /* FIXME don't raise here */
3741         g_assert_not_reached ();
3742 }
3743
3744 static guint32 
3745 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3746 {
3747         guint32 idx;
3748         MonoDynamicTable *table;
3749         guint32 *values;
3750
3751         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3752         idx = table->next_idx ++;
3753         table->rows ++;
3754         alloc_table (table, table->rows);
3755         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3756
3757         values [MONO_STAND_ALONE_SIGNATURE] =
3758                 mono_reflection_encode_sighelper (assembly, helper);
3759
3760         return idx;
3761 }
3762
3763 static int
3764 reflection_cc_to_file (int call_conv) {
3765         switch (call_conv & 0x3) {
3766         case 0:
3767         case 1: return MONO_CALL_DEFAULT;
3768         case 2: return MONO_CALL_VARARG;
3769         default:
3770                 g_assert_not_reached ();
3771         }
3772         return 0;
3773 }
3774 #endif /* !DISABLE_REFLECTION_EMIT */
3775
3776 typedef struct {
3777         MonoType *parent;
3778         MonoMethodSignature *sig;
3779         char *name;
3780         guint32 token;
3781 } ArrayMethod;
3782
3783 #ifndef DISABLE_REFLECTION_EMIT
3784 static guint32
3785 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3786 {
3787         MonoError error;
3788         guint32 nparams, i;
3789         GList *tmp;
3790         char *name;
3791         MonoMethodSignature *sig;
3792         ArrayMethod *am;
3793         MonoType *mtype;
3794
3795         name = mono_string_to_utf8 (m->name);
3796         nparams = mono_array_length (m->parameters);
3797         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3798         sig->hasthis = 1;
3799         sig->sentinelpos = -1;
3800         sig->call_convention = reflection_cc_to_file (m->call_conv);
3801         sig->param_count = nparams;
3802         if (m->ret) {
3803                 sig->ret = mono_reflection_type_get_handle (m->ret, &error);
3804                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3805         } else
3806                 sig->ret = &mono_defaults.void_class->byval_arg;
3807
3808         mtype = mono_reflection_type_get_handle (m->parent, &error);
3809         mono_error_raise_exception (&error); /* FIXME don't raise here */
3810
3811         for (i = 0; i < nparams; ++i) {
3812                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, &error);
3813                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3814         }
3815
3816         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3817                 am = (ArrayMethod *)tmp->data;
3818                 if (strcmp (name, am->name) == 0 && 
3819                                 mono_metadata_type_equal (am->parent, mtype) &&
3820                                 mono_metadata_signature_equal (am->sig, sig)) {
3821                         g_free (name);
3822                         g_free (sig);
3823                         m->table_idx = am->token & 0xffffff;
3824                         return am->token;
3825                 }
3826         }
3827         am = g_new0 (ArrayMethod, 1);
3828         am->name = name;
3829         am->sig = sig;
3830         am->parent = mtype;
3831         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3832                 method_encode_signature (assembly, sig));
3833         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3834         m->table_idx = am->token & 0xffffff;
3835         return am->token;
3836 }
3837
3838 /*
3839  * Insert into the metadata tables all the info about the TypeBuilder tb.
3840  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3841  */
3842 static gboolean
3843 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3844 {
3845         MonoDynamicTable *table;
3846         guint *values;
3847         int i, is_object = 0, is_system = 0;
3848         char *n;
3849
3850         mono_error_init (error);
3851
3852         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3853         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3854         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3855         n = mono_string_to_utf8 (tb->name);
3856         if (strcmp (n, "Object") == 0)
3857                 is_object++;
3858         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3859         g_free (n);
3860         n = mono_string_to_utf8 (tb->nspace);
3861         if (strcmp (n, "System") == 0)
3862                 is_system++;
3863         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3864         g_free (n);
3865         if (tb->parent && !(is_system && is_object) && 
3866                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3867                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3868                 return_val_if_nok (error, FALSE);
3869                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3870         } else {
3871                 values [MONO_TYPEDEF_EXTENDS] = 0;
3872         }
3873         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3874         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3875
3876         /*
3877          * if we have explicitlayout or sequentiallayouts, output data in the
3878          * ClassLayout table.
3879          */
3880         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3881                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3882                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3883                 table->rows++;
3884                 alloc_table (table, table->rows);
3885                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3886                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3887                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3888                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3889         }
3890
3891         /* handle interfaces */
3892         if (tb->interfaces) {
3893                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3894                 i = table->rows;
3895                 table->rows += mono_array_length (tb->interfaces);
3896                 alloc_table (table, table->rows);
3897                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3898                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3899                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3900                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3901                         return_val_if_nok (error, FALSE);
3902                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3903                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3904                         values += MONO_INTERFACEIMPL_SIZE;
3905                 }
3906         }
3907
3908         /* handle fields */
3909         if (tb->fields) {
3910                 table = &assembly->tables [MONO_TABLE_FIELD];
3911                 table->rows += tb->num_fields;
3912                 alloc_table (table, table->rows);
3913                 for (i = 0; i < tb->num_fields; ++i)
3914                         mono_image_get_field_info (
3915                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3916         }
3917
3918         /* handle constructors */
3919         if (tb->ctors) {
3920                 table = &assembly->tables [MONO_TABLE_METHOD];
3921                 table->rows += mono_array_length (tb->ctors);
3922                 alloc_table (table, table->rows);
3923                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3924                         if (!mono_image_get_ctor_info (domain,
3925                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3926                                                        assembly, error))
3927                                 return FALSE;
3928                 }
3929         }
3930
3931         /* handle methods */
3932         if (tb->methods) {
3933                 table = &assembly->tables [MONO_TABLE_METHOD];
3934                 table->rows += tb->num_methods;
3935                 alloc_table (table, table->rows);
3936                 for (i = 0; i < tb->num_methods; ++i) {
3937                         if (!mono_image_get_method_info (
3938                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3939                                 return FALSE;
3940                 }
3941         }
3942
3943         /* Do the same with properties etc.. */
3944         if (tb->events && mono_array_length (tb->events)) {
3945                 table = &assembly->tables [MONO_TABLE_EVENT];
3946                 table->rows += mono_array_length (tb->events);
3947                 alloc_table (table, table->rows);
3948                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3949                 table->rows ++;
3950                 alloc_table (table, table->rows);
3951                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3952                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3953                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3954                 for (i = 0; i < mono_array_length (tb->events); ++i)
3955                         mono_image_get_event_info (
3956                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3957         }
3958         if (tb->properties && mono_array_length (tb->properties)) {
3959                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3960                 table->rows += mono_array_length (tb->properties);
3961                 alloc_table (table, table->rows);
3962                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3963                 table->rows ++;
3964                 alloc_table (table, table->rows);
3965                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3966                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3967                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3968                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3969                         mono_image_get_property_info (
3970                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3971         }
3972
3973         /* handle generic parameters */
3974         if (tb->generic_params) {
3975                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3976                 table->rows += mono_array_length (tb->generic_params);
3977                 alloc_table (table, table->rows);
3978                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3979                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3980
3981                         mono_image_get_generic_param_info (
3982                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3983                 }
3984         }
3985
3986         mono_image_add_decl_security (assembly, 
3987                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3988
3989         if (tb->subtypes) {
3990                 MonoDynamicTable *ntable;
3991                 
3992                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3993                 ntable->rows += mono_array_length (tb->subtypes);
3994                 alloc_table (ntable, ntable->rows);
3995                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3996
3997                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3998                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3999
4000                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4001                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4002                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4003                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4004                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4005                                 ntable->next_idx, ntable->rows);*/
4006                         values += MONO_NESTED_CLASS_SIZE;
4007                         ntable->next_idx++;
4008                 }
4009         }
4010
4011         return TRUE;
4012 }
4013 #endif
4014
4015 static void
4016 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4017 {
4018         int i;
4019
4020         mono_ptr_array_append (*types, type);
4021
4022         if (!type->subtypes)
4023                 return;
4024
4025         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4026                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4027                 collect_types (types, subtype);
4028         }
4029 }
4030
4031 static gint
4032 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4033 {
4034         if ((*type1)->table_idx < (*type2)->table_idx)
4035                 return -1;
4036         else
4037                 if ((*type1)->table_idx > (*type2)->table_idx)
4038                         return 1;
4039         else
4040                 return 0;
4041 }
4042
4043 static gboolean
4044 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4045         int i;
4046
4047         mono_error_init (error);
4048         if (!pinfo)
4049                 return TRUE;
4050         for (i = 0; i < mono_array_length (pinfo); ++i) {
4051                 MonoReflectionParamBuilder *pb;
4052                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4053                 if (!pb)
4054                         continue;
4055                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4056                         return FALSE;
4057         }
4058
4059         return TRUE;
4060 }
4061
4062 static gboolean
4063 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4064         int i;
4065
4066         mono_error_init (error);
4067         
4068         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4069                 return FALSE;
4070         if (tb->fields) {
4071                 for (i = 0; i < tb->num_fields; ++i) {
4072                         MonoReflectionFieldBuilder* fb;
4073                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4074                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4075                                 return FALSE;
4076                 }
4077         }
4078         if (tb->events) {
4079                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4080                         MonoReflectionEventBuilder* eb;
4081                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4082                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4083                                 return FALSE;
4084                 }
4085         }
4086         if (tb->properties) {
4087                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4088                         MonoReflectionPropertyBuilder* pb;
4089                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4090                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4091                                 return FALSE;
4092                 }
4093         }
4094         if (tb->ctors) {
4095                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4096                         MonoReflectionCtorBuilder* cb;
4097                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4098                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4099                             !params_add_cattrs (assembly, cb->pinfo, error))
4100                                 return FALSE;
4101                 }
4102         }
4103
4104         if (tb->methods) {
4105                 for (i = 0; i < tb->num_methods; ++i) {
4106                         MonoReflectionMethodBuilder* mb;
4107                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4108                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4109                             !params_add_cattrs (assembly, mb->pinfo, error))
4110                                 return FALSE;
4111                 }
4112         }
4113
4114         if (tb->subtypes) {
4115                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4116                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4117                                 return FALSE;
4118                 }
4119         }
4120
4121         return TRUE;
4122 }
4123
4124 static gboolean
4125 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4126 {
4127         int i;
4128         
4129         mono_error_init (error);
4130
4131         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4132                 return FALSE;
4133
4134         if (moduleb->global_methods) {
4135                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4136                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4137                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4138                             !params_add_cattrs (assembly, mb->pinfo, error))
4139                                 return FALSE;
4140                 }
4141         }
4142
4143         if (moduleb->global_fields) {
4144                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4145                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4146                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4147                                 return FALSE;
4148                 }
4149         }
4150         
4151         if (moduleb->types) {
4152                 for (i = 0; i < moduleb->num_types; ++i) {
4153                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4154                                 return FALSE;
4155                 }
4156         }
4157
4158         return TRUE;
4159 }
4160
4161 static void
4162 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4163 {
4164         MonoDynamicTable *table;
4165         guint32 *values;
4166         char blob_size [6];
4167         guchar hash [20];
4168         char *b = blob_size;
4169         char *dir, *path;
4170
4171         table = &assembly->tables [MONO_TABLE_FILE];
4172         table->rows++;
4173         alloc_table (table, table->rows);
4174         values = table->values + table->next_idx * MONO_FILE_SIZE;
4175         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4176         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4177         if (image_is_dynamic (module->image)) {
4178                 /* This depends on the fact that the main module is emitted last */
4179                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4180                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4181         } else {
4182                 dir = NULL;
4183                 path = g_strdup (module->image->name);
4184         }
4185         mono_sha1_get_digest_from_file (path, hash);
4186         g_free (dir);
4187         g_free (path);
4188         mono_metadata_encode_value (20, b, &b);
4189         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4190         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4191         table->next_idx ++;
4192 }
4193
4194 static void
4195 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4196 {
4197         MonoDynamicTable *table;
4198         int i;
4199
4200         table = &assembly->tables [MONO_TABLE_MODULE];
4201         mb->table_idx = table->next_idx ++;
4202         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4203         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4204         i /= 16;
4205         ++i;
4206         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4207         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4208         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4209         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4210 }
4211
4212 static guint32
4213 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4214         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4215 {
4216         MonoDynamicTable *table;
4217         guint32 *values;
4218         guint32 visib, res;
4219
4220         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4221         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4222                 return 0;
4223
4224         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4225         table->rows++;
4226         alloc_table (table, table->rows);
4227         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4228
4229         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4230         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4231         if (klass->nested_in)
4232                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4233         else
4234                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4235         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4236         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4237
4238         res = table->next_idx;
4239
4240         table->next_idx ++;
4241
4242         /* Emit nested types */
4243         if (klass->ext && klass->ext->nested_classes) {
4244                 GList *tmp;
4245
4246                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4247                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4248         }
4249
4250         return res;
4251 }
4252
4253 static void
4254 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4255         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4256 {
4257         MonoError error;
4258         MonoClass *klass;
4259         guint32 idx, i;
4260
4261         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
4262         mono_error_raise_exception (&error); /* FIXME don't raise here */
4263
4264         klass = mono_class_from_mono_type (t);
4265
4266         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4267
4268         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4269                                                                                                    parent_index, assembly);
4270
4271         /* 
4272          * Emit nested types
4273          * We need to do this ourselves since klass->nested_classes is not set up.
4274          */
4275         if (tb->subtypes) {
4276                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4277                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4278         }
4279 }
4280
4281 static void
4282 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4283         guint32 module_index, MonoDynamicImage *assembly)
4284 {
4285         MonoImage *image = module->image;
4286         MonoTableInfo  *t;
4287         guint32 i;
4288
4289         t = &image->tables [MONO_TABLE_TYPEDEF];
4290
4291         for (i = 0; i < t->rows; ++i) {
4292                 MonoError error;
4293                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4294                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4295
4296                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4297                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4298         }
4299 }
4300
4301 static void
4302 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4303 {
4304         MonoDynamicTable *table;
4305         guint32 *values;
4306         guint32 scope, scope_idx, impl, current_idx;
4307         gboolean forwarder = TRUE;
4308         gpointer iter = NULL;
4309         MonoClass *nested;
4310
4311         if (klass->nested_in) {
4312                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4313                 forwarder = FALSE;
4314         } else {
4315                 scope = resolution_scope_from_image (assembly, klass->image);
4316                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4317                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4318                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4319         }
4320
4321         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4322
4323         table->rows++;
4324         alloc_table (table, table->rows);
4325         current_idx = table->next_idx;
4326         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4327
4328         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4329         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4330         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4331         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4332         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4333
4334         table->next_idx++;
4335
4336         while ((nested = mono_class_get_nested_types (klass, &iter)))
4337                 add_exported_type (assemblyb, assembly, nested, current_idx);
4338 }
4339
4340 static void
4341 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4342 {
4343         MonoError error;
4344         MonoClass *klass;
4345         int i;
4346
4347         if (!assemblyb->type_forwarders)
4348                 return;
4349
4350         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4351                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4352                 MonoType *type;
4353                 if (!t)
4354                         continue;
4355
4356                 type = mono_reflection_type_get_handle (t, &error);
4357                 mono_error_assert_ok (&error);
4358                 g_assert (type);
4359
4360                 klass = mono_class_from_mono_type (type);
4361
4362                 add_exported_type (assemblyb, assembly, klass, 0);
4363         }
4364 }
4365
4366 #define align_pointer(base,p)\
4367         do {\
4368                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4369                 if (__diff & 3)\
4370                         (p) += 4 - (__diff & 3);\
4371         } while (0)
4372
4373 static int
4374 compare_constants (const void *a, const void *b)
4375 {
4376         const guint32 *a_values = (const guint32 *)a;
4377         const guint32 *b_values = (const guint32 *)b;
4378         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4379 }
4380
4381 static int
4382 compare_semantics (const void *a, const void *b)
4383 {
4384         const guint32 *a_values = (const guint32 *)a;
4385         const guint32 *b_values = (const guint32 *)b;
4386         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4387         if (assoc)
4388                 return assoc;
4389         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4390 }
4391
4392 static int
4393 compare_custom_attrs (const void *a, const void *b)
4394 {
4395         const guint32 *a_values = (const guint32 *)a;
4396         const guint32 *b_values = (const guint32 *)b;
4397
4398         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4399 }
4400
4401 static int
4402 compare_field_marshal (const void *a, const void *b)
4403 {
4404         const guint32 *a_values = (const guint32 *)a;
4405         const guint32 *b_values = (const guint32 *)b;
4406
4407         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4408 }
4409
4410 static int
4411 compare_nested (const void *a, const void *b)
4412 {
4413         const guint32 *a_values = (const guint32 *)a;
4414         const guint32 *b_values = (const guint32 *)b;
4415
4416         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4417 }
4418
4419 static int
4420 compare_genericparam (const void *a, const void *b)
4421 {
4422         MonoError error;
4423         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4424         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4425
4426         if ((*b_entry)->owner == (*a_entry)->owner) {
4427                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4428                 mono_error_assert_ok (&error);
4429                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4430                 mono_error_assert_ok (&error);
4431                 return 
4432                         mono_type_get_generic_param_num (a_type) -
4433                         mono_type_get_generic_param_num (b_type);
4434         } else
4435                 return (*a_entry)->owner - (*b_entry)->owner;
4436 }
4437
4438 static int
4439 compare_declsecurity_attrs (const void *a, const void *b)
4440 {
4441         const guint32 *a_values = (const guint32 *)a;
4442         const guint32 *b_values = (const guint32 *)b;
4443
4444         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4445 }
4446
4447 static int
4448 compare_interface_impl (const void *a, const void *b)
4449 {
4450         const guint32 *a_values = (const guint32 *)a;
4451         const guint32 *b_values = (const guint32 *)b;
4452
4453         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4454         if (klass)
4455                 return klass;
4456
4457         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4458 }
4459
4460 static void
4461 pad_heap (MonoDynamicStream *sh)
4462 {
4463         if (sh->index & 3) {
4464                 int sz = 4 - (sh->index & 3);
4465                 memset (sh->data + sh->index, 0, sz);
4466                 sh->index += sz;
4467         }
4468 }
4469
4470 struct StreamDesc {
4471         const char *name;
4472         MonoDynamicStream *stream;
4473 };
4474
4475 /*
4476  * build_compressed_metadata() fills in the blob of data that represents the 
4477  * raw metadata as it will be saved in the PE file. The five streams are output 
4478  * and the metadata tables are comnpressed from the guint32 array representation, 
4479  * to the compressed on-disk format.
4480  */
4481 static gboolean
4482 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4483 {
4484         MonoDynamicTable *table;
4485         int i;
4486         guint64 valid_mask = 0;
4487         guint64 sorted_mask;
4488         guint32 heapt_size = 0;
4489         guint32 meta_size = 256; /* allow for header and other stuff */
4490         guint32 table_offset;
4491         guint32 ntables = 0;
4492         guint64 *int64val;
4493         guint32 *int32val;
4494         guint16 *int16val;
4495         MonoImage *meta;
4496         unsigned char *p;
4497         struct StreamDesc stream_desc [5];
4498
4499         mono_error_init (error);
4500
4501         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4502         for (i = 0; i < assembly->gen_params->len; i++) {
4503                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4504                 if (!write_generic_param_entry (assembly, entry, error))
4505                         return FALSE;
4506         }
4507
4508         stream_desc [0].name  = "#~";
4509         stream_desc [0].stream = &assembly->tstream;
4510         stream_desc [1].name  = "#Strings";
4511         stream_desc [1].stream = &assembly->sheap;
4512         stream_desc [2].name  = "#US";
4513         stream_desc [2].stream = &assembly->us;
4514         stream_desc [3].name  = "#Blob";
4515         stream_desc [3].stream = &assembly->blob;
4516         stream_desc [4].name  = "#GUID";
4517         stream_desc [4].stream = &assembly->guid;
4518         
4519         /* tables that are sorted */
4520         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4521                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4522                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4523                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4524                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4525                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4526                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4527         
4528         /* Compute table sizes */
4529         /* the MonoImage has already been created in mono_image_basic_init() */
4530         meta = &assembly->image;
4531
4532         /* sizes should be multiple of 4 */
4533         pad_heap (&assembly->blob);
4534         pad_heap (&assembly->guid);
4535         pad_heap (&assembly->sheap);
4536         pad_heap (&assembly->us);
4537
4538         /* Setup the info used by compute_sizes () */
4539         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4540         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4541         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4542
4543         meta_size += assembly->blob.index;
4544         meta_size += assembly->guid.index;
4545         meta_size += assembly->sheap.index;
4546         meta_size += assembly->us.index;
4547
4548         for (i=0; i < MONO_TABLE_NUM; ++i)
4549                 meta->tables [i].rows = assembly->tables [i].rows;
4550         
4551         for (i = 0; i < MONO_TABLE_NUM; i++){
4552                 if (meta->tables [i].rows == 0)
4553                         continue;
4554                 valid_mask |= (guint64)1 << i;
4555                 ntables ++;
4556                 meta->tables [i].row_size = mono_metadata_compute_size (
4557                         meta, i, &meta->tables [i].size_bitfield);
4558                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4559         }
4560         heapt_size += 24; /* #~ header size */
4561         heapt_size += ntables * 4;
4562         /* make multiple of 4 */
4563         heapt_size += 3;
4564         heapt_size &= ~3;
4565         meta_size += heapt_size;
4566         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4567         p = (unsigned char*)meta->raw_metadata;
4568         /* the metadata signature */
4569         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4570         /* version numbers and 4 bytes reserved */
4571         int16val = (guint16*)p;
4572         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4573         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4574         p += 8;
4575         /* version string */
4576         int32val = (guint32*)p;
4577         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4578         p += 4;
4579         memcpy (p, meta->version, strlen (meta->version));
4580         p += GUINT32_FROM_LE (*int32val);
4581         align_pointer (meta->raw_metadata, p);
4582         int16val = (guint16*)p;
4583         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4584         *int16val = GUINT16_TO_LE (5); /* number of streams */
4585         p += 4;
4586
4587         /*
4588          * write the stream info.
4589          */
4590         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4591         table_offset += 3; table_offset &= ~3;
4592
4593         assembly->tstream.index = heapt_size;
4594         for (i = 0; i < 5; ++i) {
4595                 int32val = (guint32*)p;
4596                 stream_desc [i].stream->offset = table_offset;
4597                 *int32val++ = GUINT32_TO_LE (table_offset);
4598                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4599                 table_offset += GUINT32_FROM_LE (*int32val);
4600                 table_offset += 3; table_offset &= ~3;
4601                 p += 8;
4602                 strcpy ((char*)p, stream_desc [i].name);
4603                 p += strlen (stream_desc [i].name) + 1;
4604                 align_pointer (meta->raw_metadata, p);
4605         }
4606         /* 
4607          * now copy the data, the table stream header and contents goes first.
4608          */
4609         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4610         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4611         int32val = (guint32*)p;
4612         *int32val = GUINT32_TO_LE (0); /* reserved */
4613         p += 4;
4614
4615         *p++ = 2; /* version */
4616         *p++ = 0;
4617
4618         if (meta->idx_string_wide)
4619                 *p |= 0x01;
4620         if (meta->idx_guid_wide)
4621                 *p |= 0x02;
4622         if (meta->idx_blob_wide)
4623                 *p |= 0x04;
4624         ++p;
4625         *p++ = 1; /* reserved */
4626         int64val = (guint64*)p;
4627         *int64val++ = GUINT64_TO_LE (valid_mask);
4628         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4629         p += 16;
4630         int32val = (guint32*)p;
4631         for (i = 0; i < MONO_TABLE_NUM; i++){
4632                 if (meta->tables [i].rows == 0)
4633                         continue;
4634                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4635         }
4636         p = (unsigned char*)int32val;
4637
4638         /* sort the tables that still need sorting */
4639         table = &assembly->tables [MONO_TABLE_CONSTANT];
4640         if (table->rows)
4641                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4642         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4643         if (table->rows)
4644                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4645         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4646         if (table->rows)
4647                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4648         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4649         if (table->rows)
4650                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4651         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4652         if (table->rows)
4653                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4654         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4655         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4656         if (table->rows)
4657                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4658         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4659         if (table->rows)
4660                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4661
4662         /* compress the tables */
4663         for (i = 0; i < MONO_TABLE_NUM; i++){
4664                 int row, col;
4665                 guint32 *values;
4666                 guint32 bitfield = meta->tables [i].size_bitfield;
4667                 if (!meta->tables [i].rows)
4668                         continue;
4669                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4670                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4671                 meta->tables [i].base = (char*)p;
4672                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4673                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4674                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4675                                 switch (mono_metadata_table_size (bitfield, col)) {
4676                                 case 1:
4677                                         *p++ = values [col];
4678                                         break;
4679                                 case 2:
4680                                         *p++ = values [col] & 0xff;
4681                                         *p++ = (values [col] >> 8) & 0xff;
4682                                         break;
4683                                 case 4:
4684                                         *p++ = values [col] & 0xff;
4685                                         *p++ = (values [col] >> 8) & 0xff;
4686                                         *p++ = (values [col] >> 16) & 0xff;
4687                                         *p++ = (values [col] >> 24) & 0xff;
4688                                         break;
4689                                 default:
4690                                         g_assert_not_reached ();
4691                                 }
4692                         }
4693                 }
4694                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4695         }
4696         
4697         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4698         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4699         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4700         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4701         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4702
4703         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4704
4705         return TRUE;
4706 }
4707
4708 /*
4709  * Some tables in metadata need to be sorted according to some criteria, but
4710  * when methods and fields are first created with reflection, they may be assigned a token
4711  * that doesn't correspond to the final token they will get assigned after the sorting.
4712  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4713  * with the reflection objects that represent them. Once all the tables are set up, the 
4714  * reflection objects will contains the correct table index. fixup_method() will fixup the
4715  * tokens for the method with ILGenerator @ilgen.
4716  */
4717 static void
4718 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4719 {
4720         guint32 code_idx = GPOINTER_TO_UINT (value);
4721         MonoReflectionILTokenInfo *iltoken;
4722         MonoReflectionFieldBuilder *field;
4723         MonoReflectionCtorBuilder *ctor;
4724         MonoReflectionMethodBuilder *method;
4725         MonoReflectionTypeBuilder *tb;
4726         MonoReflectionArrayMethod *am;
4727         guint32 i, idx = 0;
4728         unsigned char *target;
4729
4730         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4731                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4732                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4733                 switch (target [3]) {
4734                 case MONO_TABLE_FIELD:
4735                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4736                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4737                                 idx = field->table_idx;
4738                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4739                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4740                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4741                         } else {
4742                                 g_assert_not_reached ();
4743                         }
4744                         break;
4745                 case MONO_TABLE_METHOD:
4746                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4747                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4748                                 idx = method->table_idx;
4749                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4750                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4751                                 idx = ctor->table_idx;
4752                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4753                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4754                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4755                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4756                         } else {
4757                                 g_assert_not_reached ();
4758                         }
4759                         break;
4760                 case MONO_TABLE_TYPEDEF:
4761                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4762                                 g_assert_not_reached ();
4763                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4764                         idx = tb->table_idx;
4765                         break;
4766                 case MONO_TABLE_MEMBERREF:
4767                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4768                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4769                                 idx = am->table_idx;
4770                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4771                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4772                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4773                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4774                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4775                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4776                                 continue;
4777                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4778                                 continue;
4779                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4780                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4781                                 g_assert (is_field_on_inst (f));
4782                                 continue;
4783                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4784                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4785                                 continue;
4786                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4787                                 continue;
4788                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4789                                 continue;
4790                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4791                                 continue;
4792                         } else {
4793                                 g_assert_not_reached ();
4794                         }
4795                         break;
4796                 case MONO_TABLE_METHODSPEC:
4797                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4798                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4799                                 g_assert (mono_method_signature (m)->generic_param_count);
4800                                 continue;
4801                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4802                                 continue;
4803                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4804                                 continue;
4805                         } else {
4806                                 g_assert_not_reached ();
4807                         }
4808                         break;
4809                 default:
4810                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4811                 }
4812                 target [0] = idx & 0xff;
4813                 target [1] = (idx >> 8) & 0xff;
4814                 target [2] = (idx >> 16) & 0xff;
4815         }
4816 }
4817
4818 /*
4819  * fixup_cattrs:
4820  *
4821  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4822  * value is not known when the table is emitted.
4823  */
4824 static void
4825 fixup_cattrs (MonoDynamicImage *assembly)
4826 {
4827         MonoDynamicTable *table;
4828         guint32 *values;
4829         guint32 type, i, idx, token;
4830         MonoObject *ctor;
4831
4832         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4833
4834         for (i = 0; i < table->rows; ++i) {
4835                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4836
4837                 type = values [MONO_CUSTOM_ATTR_TYPE];
4838                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4839                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4840                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4841                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4842                         g_assert (ctor);
4843
4844                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4845                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4846                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4847                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4848                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4849                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4850                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4851                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4852                         }
4853                 }
4854         }
4855 }
4856
4857 static void
4858 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4859 {
4860         MonoDynamicTable *table;
4861         guint32 *values;
4862
4863         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4864         table->rows++;
4865         alloc_table (table, table->rows);
4866         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4867         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4868         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4869         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4870         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4871         table->next_idx++;
4872 }
4873
4874 static void
4875 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4876 {
4877         MonoDynamicTable *table;
4878         guint32 *values;
4879         char blob_size [6];
4880         guchar hash [20];
4881         char *b = blob_size;
4882         char *name, *sname;
4883         guint32 idx, offset;
4884
4885         if (rsrc->filename) {
4886                 name = mono_string_to_utf8 (rsrc->filename);
4887                 sname = g_path_get_basename (name);
4888         
4889                 table = &assembly->tables [MONO_TABLE_FILE];
4890                 table->rows++;
4891                 alloc_table (table, table->rows);
4892                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4893                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4894                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4895                 g_free (sname);
4896
4897                 mono_sha1_get_digest_from_file (name, hash);
4898                 mono_metadata_encode_value (20, b, &b);
4899                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4900                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4901                 g_free (name);
4902                 idx = table->next_idx++;
4903                 rsrc->offset = 0;
4904                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4905         } else {
4906                 char sizebuf [4];
4907                 char *data;
4908                 guint len;
4909                 if (rsrc->data) {
4910                         data = mono_array_addr (rsrc->data, char, 0);
4911                         len = mono_array_length (rsrc->data);
4912                 } else {
4913                         data = NULL;
4914                         len = 0;
4915                 }
4916                 offset = len;
4917                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4918                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4919                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4920                 mono_image_add_stream_data (&assembly->resources, data, len);
4921
4922                 if (!mb->is_main)
4923                         /* 
4924                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4925                          * the main module, but that needs to reference the FILE table
4926                          * which isn't emitted yet.
4927                          */
4928                         return;
4929                 else
4930                         idx = 0;
4931         }
4932
4933         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4934 }
4935
4936 static void
4937 set_version_from_string (MonoString *version, guint32 *values)
4938 {
4939         gchar *ver, *p, *str;
4940         guint32 i;
4941         
4942         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4943         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4944         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4945         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4946         if (!version)
4947                 return;
4948         ver = str = mono_string_to_utf8 (version);
4949         for (i = 0; i < 4; ++i) {
4950                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4951                 switch (*p) {
4952                 case '.':
4953                         p++;
4954                         break;
4955                 case '*':
4956                         /* handle Revision and Build */
4957                         p++;
4958                         break;
4959                 }
4960                 ver = p;
4961         }
4962         g_free (str);
4963 }
4964
4965 static guint32
4966 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4967         gsize len;
4968         guint32 token = 0;
4969         char blob_size [6];
4970         char *b = blob_size;
4971
4972         if (!pkey)
4973                 return token;
4974
4975         len = mono_array_length (pkey);
4976         mono_metadata_encode_value (len, b, &b);
4977         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4978         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4979
4980         assembly->public_key = (guint8 *)g_malloc (len);
4981         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4982         assembly->public_key_len = len;
4983
4984         /* Special case: check for ECMA key (16 bytes) */
4985         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4986                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4987                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4988         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4989                 /* minimum key size (in 2.0) is 384 bits */
4990                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4991         } else {
4992                 /* FIXME - verifier */
4993                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4994                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4995         }
4996         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4997
4998         return token;
4999 }
5000
5001 static void
5002 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
5003 {
5004         MonoDynamicTable *table;
5005         MonoDynamicImage *assembly;
5006         MonoReflectionAssemblyBuilder *assemblyb;
5007         MonoDomain *domain;
5008         guint32 *values;
5009         int i;
5010         guint32 module_index;
5011
5012         assemblyb = moduleb->assemblyb;
5013         assembly = moduleb->dynamic_image;
5014         domain = mono_object_domain (assemblyb);
5015
5016         /* Emit ASSEMBLY table */
5017         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5018         alloc_table (table, 1);
5019         values = table->values + MONO_ASSEMBLY_SIZE;
5020         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5021         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5022         if (assemblyb->culture) {
5023                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5024         } else {
5025                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5026         }
5027         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5028         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5029         set_version_from_string (assemblyb->version, values);
5030
5031         /* Emit FILE + EXPORTED_TYPE table */
5032         module_index = 0;
5033         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5034                 int j;
5035                 MonoReflectionModuleBuilder *file_module = 
5036                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5037                 if (file_module != moduleb) {
5038                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5039                         module_index ++;
5040                         if (file_module->types) {
5041                                 for (j = 0; j < file_module->num_types; ++j) {
5042                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5043                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
5044                                 }
5045                         }
5046                 }
5047         }
5048         if (assemblyb->loaded_modules) {
5049                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5050                         MonoReflectionModule *file_module = 
5051                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5052                         mono_image_fill_file_table (domain, file_module, assembly);
5053                         module_index ++;
5054                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5055                 }
5056         }
5057         if (assemblyb->type_forwarders)
5058                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5059
5060         /* Emit MANIFESTRESOURCE table */
5061         module_index = 0;
5062         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5063                 int j;
5064                 MonoReflectionModuleBuilder *file_module = 
5065                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5066                 /* The table for the main module is emitted later */
5067                 if (file_module != moduleb) {
5068                         module_index ++;
5069                         if (file_module->resources) {
5070                                 int len = mono_array_length (file_module->resources);
5071                                 for (j = 0; j < len; ++j) {
5072                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5073                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5074                                 }
5075                         }
5076                 }
5077         }               
5078 }
5079
5080 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5081
5082 /*
5083  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5084  * for the modulebuilder @moduleb.
5085  * At the end of the process, method and field tokens are fixed up and the 
5086  * on-disk compressed metadata representation is created.
5087  * Return TRUE on success, or FALSE on failure and sets @error
5088  */
5089 gboolean
5090 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5091 {
5092         MonoDynamicTable *table;
5093         MonoDynamicImage *assembly;
5094         MonoReflectionAssemblyBuilder *assemblyb;
5095         MonoDomain *domain;
5096         MonoPtrArray types;
5097         guint32 *values;
5098         int i, j;
5099
5100         mono_error_init (error);
5101
5102         assemblyb = moduleb->assemblyb;
5103         assembly = moduleb->dynamic_image;
5104         domain = mono_object_domain (assemblyb);
5105
5106         if (assembly->text_rva)
5107                 return TRUE;
5108
5109         assembly->text_rva = START_TEXT_RVA;
5110
5111         if (moduleb->is_main) {
5112                 mono_image_emit_manifest (moduleb);
5113         }
5114
5115         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5116         table->rows = 1; /* .<Module> */
5117         table->next_idx++;
5118         alloc_table (table, table->rows);
5119         /*
5120          * Set the first entry.
5121          */
5122         values = table->values + table->columns;
5123         values [MONO_TYPEDEF_FLAGS] = 0;
5124         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5125         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5126         values [MONO_TYPEDEF_EXTENDS] = 0;
5127         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5128         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5129
5130         /* 
5131          * handle global methods 
5132          * FIXME: test what to do when global methods are defined in multiple modules.
5133          */
5134         if (moduleb->global_methods) {
5135                 table = &assembly->tables [MONO_TABLE_METHOD];
5136                 table->rows += mono_array_length (moduleb->global_methods);
5137                 alloc_table (table, table->rows);
5138                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5139                         if (!mono_image_get_method_info (
5140                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5141                                 goto leave;
5142                 }
5143         }
5144         if (moduleb->global_fields) {
5145                 table = &assembly->tables [MONO_TABLE_FIELD];
5146                 table->rows += mono_array_length (moduleb->global_fields);
5147                 alloc_table (table, table->rows);
5148                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
5149                         mono_image_get_field_info (
5150                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
5151         }
5152
5153         table = &assembly->tables [MONO_TABLE_MODULE];
5154         alloc_table (table, 1);
5155         mono_image_fill_module_table (domain, moduleb, assembly);
5156
5157         /* Collect all types into a list sorted by their table_idx */
5158         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5159
5160         if (moduleb->types)
5161                 for (i = 0; i < moduleb->num_types; ++i) {
5162                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5163                         collect_types (&types, type);
5164                 }
5165
5166         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5167         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5168         table->rows += mono_ptr_array_size (types);
5169         alloc_table (table, table->rows);
5170
5171         /*
5172          * Emit type names + namespaces at one place inside the string heap,
5173          * so load_class_names () needs to touch fewer pages.
5174          */
5175         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5176                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5177                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5178         }
5179         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5180                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5181                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5182         }
5183
5184         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5185                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5186                 if (!mono_image_get_type_info (domain, type, assembly, error))
5187                         goto leave_types;
5188         }
5189
5190         /* 
5191          * table->rows is already set above and in mono_image_fill_module_table.
5192          */
5193         /* add all the custom attributes at the end, once all the indexes are stable */
5194         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5195                 goto leave_types;
5196
5197         /* CAS assembly permissions */
5198         if (assemblyb->permissions_minimum)
5199                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5200         if (assemblyb->permissions_optional)
5201                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5202         if (assemblyb->permissions_refused)
5203                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5204
5205         if (!module_add_cattrs (assembly, moduleb, error))
5206                 goto leave_types;
5207
5208         /* fixup tokens */
5209         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5210
5211         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5212          * the final tokens and don't need another fixup pass. */
5213
5214         if (moduleb->global_methods) {
5215                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5216                         MonoReflectionMethodBuilder *mb = mono_array_get (
5217                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5218                         if (!mono_image_add_methodimpl (assembly, mb, error))
5219                                 goto leave_types;
5220                 }
5221         }
5222
5223         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5224                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5225                 if (type->methods) {
5226                         for (j = 0; j < type->num_methods; ++j) {
5227                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5228                                         type->methods, MonoReflectionMethodBuilder*, j);
5229
5230                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5231                                         goto leave_types;
5232                         }
5233                 }
5234         }
5235
5236         fixup_cattrs (assembly);
5237
5238 leave_types:
5239         mono_ptr_array_destroy (types);
5240 leave:
5241
5242         return mono_error_ok (error);
5243 }
5244
5245 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5246
5247 gboolean
5248 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5249 {
5250         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5251 }
5252
5253 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5254
5255
5256 typedef struct {
5257         guint32 import_lookup_table;
5258         guint32 timestamp;
5259         guint32 forwarder;
5260         guint32 name_rva;
5261         guint32 import_address_table_rva;
5262 } MonoIDT;
5263
5264 typedef struct {
5265         guint32 name_rva;
5266         guint32 flags;
5267 } MonoILT;
5268
5269 #ifndef DISABLE_REFLECTION_EMIT
5270
5271 /*
5272  * mono_image_insert_string:
5273  * @module: module builder object
5274  * @str: a string
5275  *
5276  * Insert @str into the user string stream of @module.
5277  */
5278 guint32
5279 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5280 {
5281         MonoDynamicImage *assembly;
5282         guint32 idx;
5283         char buf [16];
5284         char *b = buf;
5285         
5286         if (!module->dynamic_image)
5287                 mono_image_module_basic_init (module);
5288
5289         assembly = module->dynamic_image;
5290         
5291         if (assembly->save) {
5292                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5293                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5294 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5295         {
5296                 char *swapped = g_malloc (2 * mono_string_length (str));
5297                 const char *p = (const char*)mono_string_chars (str);
5298
5299                 swap_with_size (swapped, p, 2, mono_string_length (str));
5300                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5301                 g_free (swapped);
5302         }
5303 #else
5304                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5305 #endif
5306                 mono_image_add_stream_data (&assembly->us, "", 1);
5307         } else {
5308                 idx = assembly->us.index ++;
5309         }
5310
5311         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5312
5313         return MONO_TOKEN_STRING | idx;
5314 }
5315
5316 guint32
5317 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5318 {
5319         MonoClass *klass;
5320         guint32 token = 0;
5321         MonoMethodSignature *sig;
5322
5323         mono_error_init (error);
5324
5325         klass = obj->vtable->klass;
5326         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5327                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5328                 MonoMethodSignature *old;
5329                 guint32 sig_token, parent;
5330                 int nargs, i;
5331
5332                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5333
5334                 nargs = mono_array_length (opt_param_types);
5335                 old = mono_method_signature (method);
5336                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5337
5338                 sig->hasthis = old->hasthis;
5339                 sig->explicit_this = old->explicit_this;
5340                 sig->call_convention = old->call_convention;
5341                 sig->generic_param_count = old->generic_param_count;
5342                 sig->param_count = old->param_count + nargs;
5343                 sig->sentinelpos = old->param_count;
5344                 sig->ret = old->ret;
5345
5346                 for (i = 0; i < old->param_count; i++)
5347                         sig->params [i] = old->params [i];
5348
5349                 for (i = 0; i < nargs; i++) {
5350                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5351                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5352                         if (!is_ok (error)) goto fail;
5353                 }
5354
5355                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5356                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5357                 parent >>= MONO_TYPEDEFORREF_BITS;
5358
5359                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5360                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5361
5362                 sig_token = method_encode_signature (assembly, sig);
5363                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5364         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5365                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5366                 ReflectionMethodBuilder rmb;
5367                 guint32 parent, sig_token;
5368                 int nopt_args, nparams, ngparams, i;
5369
5370                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5371                         goto fail;
5372                 
5373                 rmb.opt_types = opt_param_types;
5374                 nopt_args = mono_array_length (opt_param_types);
5375
5376                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5377                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5378                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5379
5380                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5381                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5382                 sig->call_convention = rmb.call_conv;
5383                 sig->generic_param_count = ngparams;
5384                 sig->param_count = nparams + nopt_args;
5385                 sig->sentinelpos = nparams;
5386                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5387                 if (!is_ok (error)) goto fail;
5388
5389                 for (i = 0; i < nparams; i++) {
5390                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5391                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5392                         if (!is_ok (error)) goto fail;
5393                 }
5394
5395                 for (i = 0; i < nopt_args; i++) {
5396                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5397                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5398                         if (!is_ok (error)) goto fail;
5399                 }
5400
5401                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5402                 if (!is_ok (error))
5403                         goto fail;
5404
5405                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5406                 if (!mono_error_ok (error))
5407                         goto fail;
5408                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5409
5410                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5411                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5412
5413                 char *name = mono_string_to_utf8 (rmb.name);
5414                 token = mono_image_get_varargs_method_token (
5415                         assembly, parent, name, sig_token);
5416                 g_free (name);
5417         } else {
5418                 g_error ("requested method token for %s\n", klass->name);
5419         }
5420
5421         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5422         register_dyn_token (assembly, token, obj);
5423         return token;
5424 fail:
5425         g_assert (!mono_error_ok (error));
5426         return 0;
5427 }
5428
5429 /*
5430  * mono_image_create_token:
5431  * @assembly: a dynamic assembly
5432  * @obj:
5433  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5434  *
5435  * Get a token to insert in the IL code stream for the given MemberInfo.
5436  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5437  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5438  * entry.
5439  */
5440 guint32
5441 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5442                          gboolean create_open_instance, gboolean register_token,
5443                          MonoError *error)
5444 {
5445         MonoClass *klass;
5446         guint32 token = 0;
5447
5448         mono_error_init (error);
5449
5450         klass = obj->vtable->klass;
5451
5452         /* Check for user defined reflection objects */
5453         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5454         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5455                 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5456                 return 0;
5457         }
5458
5459         if (strcmp (klass->name, "MethodBuilder") == 0) {
5460                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5461                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5462
5463                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5464                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5465                 else {
5466                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5467                         if (!mono_error_ok (error))
5468                                 return 0;
5469                 }
5470                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5471         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5472                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5473                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5474
5475                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5476                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5477                 else {
5478                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5479                         if (!mono_error_ok (error))
5480                                 return 0;
5481                 }
5482                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5483         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5484                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5485                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5486                 if (tb->generic_params) {
5487                         token = mono_image_get_generic_field_token (assembly, fb);
5488                 } else {
5489                         if (tb->module->dynamic_image == assembly) {
5490                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5491                         } else {
5492                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5493                         }
5494                 }
5495         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5496                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5497                 if (create_open_instance && tb->generic_params) {
5498                         MonoType *type;
5499                         init_type_builder_generics (obj);
5500                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5501                         return_val_if_nok (error, 0);
5502                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5503                         token = mono_metadata_token_from_dor (token);
5504                 } else if (tb->module->dynamic_image == assembly) {
5505                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5506                 } else {
5507                         MonoType *type;
5508                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5509                         return_val_if_nok (error, 0);
5510                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5511                 }
5512         } else if (strcmp (klass->name, "MonoType") == 0) {
5513                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5514                 return_val_if_nok (error, 0);
5515                 MonoClass *mc = mono_class_from_mono_type (type);
5516                 token = mono_metadata_token_from_dor (
5517                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5518         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5519                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5520                 return_val_if_nok (error, 0);
5521                 token = mono_metadata_token_from_dor (
5522                         mono_image_typedef_or_ref (assembly, type));
5523         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5524                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5525                 return_val_if_nok (error, 0);
5526                 token = mono_metadata_token_from_dor (
5527                         mono_image_typedef_or_ref (assembly, type));
5528         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5529                    strcmp (klass->name, "MonoMethod") == 0 ||
5530                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5531                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5532                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5533                 if (m->method->is_inflated) {
5534                         if (create_open_instance)
5535                                 token = mono_image_get_methodspec_token (assembly, m->method);
5536                         else
5537                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5538                 } else if ((m->method->klass->image == &assembly->image) &&
5539                          !m->method->klass->generic_class) {
5540                         static guint32 method_table_idx = 0xffffff;
5541                         if (m->method->klass->wastypebuilder) {
5542                                 /* we use the same token as the one that was assigned
5543                                  * to the Methodbuilder.
5544                                  * FIXME: do the equivalent for Fields.
5545                                  */
5546                                 token = m->method->token;
5547                         } else {
5548                                 /*
5549                                  * Each token should have a unique index, but the indexes are
5550                                  * assigned by managed code, so we don't know about them. An
5551                                  * easy solution is to count backwards...
5552                                  */
5553                                 method_table_idx --;
5554                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5555                         }
5556                 } else {
5557                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5558                 }
5559                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5560         } else if (strcmp (klass->name, "MonoField") == 0) {
5561                 MonoReflectionField *f = (MonoReflectionField *)obj;
5562                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5563                         static guint32 field_table_idx = 0xffffff;
5564                         field_table_idx --;
5565                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5566                 } else {
5567                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5568                 }
5569                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5570         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5571                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5572                 token = mono_image_get_array_token (assembly, m);
5573         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5574                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5575                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5576         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5577                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5578                 return_val_if_nok (error, 0);
5579                 token = mono_metadata_token_from_dor (
5580                         mono_image_typedef_or_ref (assembly, type));
5581         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5582                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5583                 token = mono_image_get_field_on_inst_token (assembly, f);
5584         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5585                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5586                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5587                 if (!mono_error_ok (error))
5588                         return 0;
5589         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5590                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5591                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5592                 if (!mono_error_ok (error))
5593                         return 0;
5594         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5595                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5596                 return_val_if_nok (error, 0);
5597                 token = mono_metadata_token_from_dor (
5598                                 mono_image_typedef_or_ref (assembly, type));
5599         } else {
5600                 g_error ("requested token for %s\n", klass->name);
5601         }
5602
5603         if (register_token)
5604                 mono_image_register_token (assembly, token, obj);
5605
5606         return token;
5607 }
5608
5609 /*
5610  * mono_image_register_token:
5611  *
5612  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5613  * the Module.ResolveXXXToken () methods to work.
5614  */
5615 void
5616 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5617 {
5618         MonoObject *prev;
5619
5620         dynamic_image_lock (assembly);
5621         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5622         if (prev) {
5623                 /* There could be multiple MethodInfo objects with the same token */
5624                 //g_assert (prev == obj);
5625         } else {
5626                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5627         }
5628         dynamic_image_unlock (assembly);
5629 }
5630
5631 static MonoDynamicImage*
5632 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5633 {
5634         static const guchar entrycode [16] = {0xff, 0x25, 0};
5635         MonoDynamicImage *image;
5636         int i;
5637
5638         const char *version;
5639
5640         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5641                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5642         else
5643                 version = mono_get_runtime_info ()->runtime_version;
5644
5645 #if HAVE_BOEHM_GC
5646         /* The MonoGHashTable's need GC tracking */
5647         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5648 #else
5649         image = g_new0 (MonoDynamicImage, 1);
5650 #endif
5651
5652         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5653         
5654         /*g_print ("created image %p\n", image);*/
5655         /* keep in sync with image.c */
5656         image->image.name = assembly_name;
5657         image->image.assembly_name = image->image.name; /* they may be different */
5658         image->image.module_name = module_name;
5659         image->image.version = g_strdup (version);
5660         image->image.md_version_major = 1;
5661         image->image.md_version_minor = 1;
5662         image->image.dynamic = TRUE;
5663
5664         image->image.references = g_new0 (MonoAssembly*, 1);
5665         image->image.references [0] = NULL;
5666
5667         mono_image_init (&image->image);
5668
5669         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");
5670         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5671         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5672         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5673         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5674         image->handleref = g_hash_table_new (NULL, NULL);
5675         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");
5676         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5677         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");
5678         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");
5679         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5680         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5681         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5682         image->gen_params = g_ptr_array_new ();
5683         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5684
5685         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5686         string_heap_init (&image->sheap);
5687         mono_image_add_stream_data (&image->us, "", 1);
5688         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5689         /* import tables... */
5690         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5691         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5692         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5693         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5694         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5695         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5696         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5697         stream_data_align (&image->code);
5698
5699         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5700
5701         for (i=0; i < MONO_TABLE_NUM; ++i) {
5702                 image->tables [i].next_idx = 1;
5703                 image->tables [i].columns = table_sizes [i];
5704         }
5705
5706         image->image.assembly = (MonoAssembly*)assembly;
5707         image->run = assembly->run;
5708         image->save = assembly->save;
5709         image->pe_kind = 0x1; /* ILOnly */
5710         image->machine = 0x14c; /* I386 */
5711         
5712         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5713
5714         dynamic_images_lock ();
5715
5716         if (!dynamic_images)
5717                 dynamic_images = g_ptr_array_new ();
5718
5719         g_ptr_array_add (dynamic_images, image);
5720
5721         dynamic_images_unlock ();
5722
5723         return image;
5724 }
5725 #endif
5726
5727 static void
5728 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5729 {
5730         g_free (key);
5731 }
5732
5733 static void
5734 release_hashtable (MonoGHashTable **hash)
5735 {
5736         if (*hash) {
5737                 mono_g_hash_table_destroy (*hash);
5738                 *hash = NULL;
5739         }
5740 }
5741
5742 void
5743 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5744 {
5745         release_hashtable (&image->token_fixups);
5746         release_hashtable (&image->handleref_managed);
5747         release_hashtable (&image->tokens);
5748         release_hashtable (&image->remapped_tokens);
5749         release_hashtable (&image->generic_def_objects);
5750         release_hashtable (&image->methodspec);
5751 }
5752
5753 // Free dynamic image pass one: Free resources but not image itself
5754 void
5755 mono_dynamic_image_free (MonoDynamicImage *image)
5756 {
5757         MonoDynamicImage *di = image;
5758         GList *list;
5759         int i;
5760
5761         if (di->methodspec)
5762                 mono_g_hash_table_destroy (di->methodspec);
5763         if (di->typespec)
5764                 g_hash_table_destroy (di->typespec);
5765         if (di->typeref)
5766                 g_hash_table_destroy (di->typeref);
5767         if (di->handleref)
5768                 g_hash_table_destroy (di->handleref);
5769         if (di->handleref_managed)
5770                 mono_g_hash_table_destroy (di->handleref_managed);
5771         if (di->tokens)
5772                 mono_g_hash_table_destroy (di->tokens);
5773         if (di->remapped_tokens)
5774                 mono_g_hash_table_destroy (di->remapped_tokens);
5775         if (di->generic_def_objects)
5776                 mono_g_hash_table_destroy (di->generic_def_objects);
5777         if (di->blob_cache) {
5778                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5779                 g_hash_table_destroy (di->blob_cache);
5780         }
5781         if (di->standalonesig_cache)
5782                 g_hash_table_destroy (di->standalonesig_cache);
5783         for (list = di->array_methods; list; list = list->next) {
5784                 ArrayMethod *am = (ArrayMethod *)list->data;
5785                 g_free (am->sig);
5786                 g_free (am->name);
5787                 g_free (am);
5788         }
5789         g_list_free (di->array_methods);
5790         if (di->gen_params) {
5791                 for (i = 0; i < di->gen_params->len; i++) {
5792                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5793                         mono_gc_deregister_root ((char*) &entry->gparam);
5794                         g_free (entry);
5795                 }
5796                 g_ptr_array_free (di->gen_params, TRUE);
5797         }
5798         if (di->token_fixups)
5799                 mono_g_hash_table_destroy (di->token_fixups);
5800         if (di->method_to_table_idx)
5801                 g_hash_table_destroy (di->method_to_table_idx);
5802         if (di->field_to_table_idx)
5803                 g_hash_table_destroy (di->field_to_table_idx);
5804         if (di->method_aux_hash)
5805                 g_hash_table_destroy (di->method_aux_hash);
5806         if (di->vararg_aux_hash)
5807                 g_hash_table_destroy (di->vararg_aux_hash);
5808         g_free (di->strong_name);
5809         g_free (di->win32_res);
5810         if (di->public_key)
5811                 g_free (di->public_key);
5812
5813         /*g_print ("string heap destroy for image %p\n", di);*/
5814         mono_dynamic_stream_reset (&di->sheap);
5815         mono_dynamic_stream_reset (&di->code);
5816         mono_dynamic_stream_reset (&di->resources);
5817         mono_dynamic_stream_reset (&di->us);
5818         mono_dynamic_stream_reset (&di->blob);
5819         mono_dynamic_stream_reset (&di->tstream);
5820         mono_dynamic_stream_reset (&di->guid);
5821         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5822                 g_free (di->tables [i].values);
5823         }
5824
5825         dynamic_images_lock ();
5826
5827         if (dynamic_images)
5828                 g_ptr_array_remove (dynamic_images, di);
5829
5830         dynamic_images_unlock ();
5831 }
5832
5833 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5834 void
5835 mono_dynamic_image_free_image (MonoDynamicImage *image)
5836 {
5837         /* See create_dynamic_mono_image () */
5838 #if HAVE_BOEHM_GC
5839         /* Allocated using GC_MALLOC */
5840 #else
5841         g_free (image);
5842 #endif
5843 }
5844
5845 #ifndef DISABLE_REFLECTION_EMIT
5846
5847 /*
5848  * mono_image_basic_init:
5849  * @assembly: an assembly builder object
5850  *
5851  * Create the MonoImage that represents the assembly builder and setup some
5852  * of the helper hash table and the basic metadata streams.
5853  */
5854 void
5855 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5856 {
5857         MonoDynamicAssembly *assembly;
5858         MonoDynamicImage *image;
5859         MonoDomain *domain = mono_object_domain (assemblyb);
5860         
5861         if (assemblyb->dynamic_assembly)
5862                 return;
5863
5864 #if HAVE_BOEHM_GC
5865         /* assembly->assembly.image might be GC allocated */
5866         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5867 #else
5868         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5869 #endif
5870
5871         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5872         
5873         assembly->assembly.ref_count = 1;
5874         assembly->assembly.dynamic = TRUE;
5875         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5876         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5877         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5878         if (assemblyb->culture)
5879                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5880         else
5881                 assembly->assembly.aname.culture = g_strdup ("");
5882
5883         if (assemblyb->version) {
5884                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5885                         char **version = g_strsplit (vstr, ".", 4);
5886                         char **parts = version;
5887                         assembly->assembly.aname.major = atoi (*parts++);
5888                         assembly->assembly.aname.minor = atoi (*parts++);
5889                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5890                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5891
5892                         g_strfreev (version);
5893                         g_free (vstr);
5894         } else {
5895                         assembly->assembly.aname.major = 0;
5896                         assembly->assembly.aname.minor = 0;
5897                         assembly->assembly.aname.build = 0;
5898                         assembly->assembly.aname.revision = 0;
5899         }
5900
5901         assembly->run = assemblyb->access != 2;
5902         assembly->save = assemblyb->access != 1;
5903         assembly->domain = domain;
5904
5905         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5906         image->initial_image = TRUE;
5907         assembly->assembly.aname.name = image->image.name;
5908         assembly->assembly.image = &image->image;
5909         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5910                 /* -1 to correct for the trailing NULL byte */
5911                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5912                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5913                 }
5914                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5915         }
5916
5917         mono_domain_assemblies_lock (domain);
5918         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5919         mono_domain_assemblies_unlock (domain);
5920
5921         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5922         
5923         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5924         
5925         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5926 }
5927
5928 #endif /* !DISABLE_REFLECTION_EMIT */
5929
5930 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5931
5932 static int
5933 calc_section_size (MonoDynamicImage *assembly)
5934 {
5935         int nsections = 0;
5936
5937         /* alignment constraints */
5938         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5939         g_assert ((assembly->code.index % 4) == 0);
5940         assembly->meta_size += 3;
5941         assembly->meta_size &= ~3;
5942         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5943         g_assert ((assembly->resources.index % 4) == 0);
5944
5945         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5946         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5947         nsections++;
5948
5949         if (assembly->win32_res) {
5950                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5951
5952                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5953                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5954                 nsections++;
5955         }
5956
5957         assembly->sections [MONO_SECTION_RELOC].size = 12;
5958         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5959         nsections++;
5960
5961         return nsections;
5962 }
5963
5964 typedef struct {
5965         guint32 id;
5966         guint32 offset;
5967         GSList *children;
5968         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5969 } ResTreeNode;
5970
5971 static int
5972 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5973 {
5974         ResTreeNode *t1 = (ResTreeNode*)a;
5975         ResTreeNode *t2 = (ResTreeNode*)b;
5976
5977         return t1->id - t2->id;
5978 }
5979
5980 /*
5981  * resource_tree_create:
5982  *
5983  *  Organize the resources into a resource tree.
5984  */
5985 static ResTreeNode *
5986 resource_tree_create (MonoArray *win32_resources)
5987 {
5988         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5989         GSList *l;
5990         int i;
5991
5992         tree = g_new0 (ResTreeNode, 1);
5993         
5994         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5995                 MonoReflectionWin32Resource *win32_res =
5996                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5997
5998                 /* Create node */
5999
6000                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6001                 lang_node = g_new0 (ResTreeNode, 1);
6002                 lang_node->id = win32_res->lang_id;
6003                 lang_node->win32_res = win32_res;
6004
6005                 /* Create type node if neccesary */
6006                 type_node = NULL;
6007                 for (l = tree->children; l; l = l->next)
6008                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6009                                 type_node = (ResTreeNode*)l->data;
6010                                 break;
6011                         }
6012
6013                 if (!type_node) {
6014                         type_node = g_new0 (ResTreeNode, 1);
6015                         type_node->id = win32_res->res_type;
6016
6017                         /* 
6018                          * The resource types have to be sorted otherwise
6019                          * Windows Explorer can't display the version information.
6020                          */
6021                         tree->children = g_slist_insert_sorted (tree->children, 
6022                                 type_node, resource_tree_compare_by_id);
6023                 }
6024
6025                 /* Create res node if neccesary */
6026                 res_node = NULL;
6027                 for (l = type_node->children; l; l = l->next)
6028                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6029                                 res_node = (ResTreeNode*)l->data;
6030                                 break;
6031                         }
6032
6033                 if (!res_node) {
6034                         res_node = g_new0 (ResTreeNode, 1);
6035                         res_node->id = win32_res->res_id;
6036                         type_node->children = g_slist_append (type_node->children, res_node);
6037                 }
6038
6039                 res_node->children = g_slist_append (res_node->children, lang_node);
6040         }
6041
6042         return tree;
6043 }
6044
6045 /*
6046  * resource_tree_encode:
6047  * 
6048  *   Encode the resource tree into the format used in the PE file.
6049  */
6050 static void
6051 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6052 {
6053         char *entries;
6054         MonoPEResourceDir dir;
6055         MonoPEResourceDirEntry dir_entry;
6056         MonoPEResourceDataEntry data_entry;
6057         GSList *l;
6058         guint32 res_id_entries;
6059
6060         /*
6061          * For the format of the resource directory, see the article
6062          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6063          * Matt Pietrek
6064          */
6065
6066         memset (&dir, 0, sizeof (dir));
6067         memset (&dir_entry, 0, sizeof (dir_entry));
6068         memset (&data_entry, 0, sizeof (data_entry));
6069
6070         g_assert (sizeof (dir) == 16);
6071         g_assert (sizeof (dir_entry) == 8);
6072         g_assert (sizeof (data_entry) == 16);
6073
6074         node->offset = p - begin;
6075
6076         /* IMAGE_RESOURCE_DIRECTORY */
6077         res_id_entries = g_slist_length (node->children);
6078         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6079
6080         memcpy (p, &dir, sizeof (dir));
6081         p += sizeof (dir);
6082
6083         /* Reserve space for entries */
6084         entries = p;
6085         p += sizeof (dir_entry) * res_id_entries;
6086
6087         /* Write children */
6088         for (l = node->children; l; l = l->next) {
6089                 ResTreeNode *child = (ResTreeNode*)l->data;
6090
6091                 if (child->win32_res) {
6092                         guint32 size;
6093
6094                         child->offset = p - begin;
6095
6096                         /* IMAGE_RESOURCE_DATA_ENTRY */
6097                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6098                         size = mono_array_length (child->win32_res->res_data);
6099                         data_entry.rde_size = GUINT32_TO_LE (size);
6100
6101                         memcpy (p, &data_entry, sizeof (data_entry));
6102                         p += sizeof (data_entry);
6103
6104                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6105                         p += size;
6106                 } else {
6107                         resource_tree_encode (child, begin, p, &p);
6108                 }
6109         }
6110
6111         /* IMAGE_RESOURCE_ENTRY */
6112         for (l = node->children; l; l = l->next) {
6113                 ResTreeNode *child = (ResTreeNode*)l->data;
6114
6115                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6116                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6117
6118                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6119                 entries += sizeof (dir_entry);
6120         }
6121
6122         *endbuf = p;
6123 }
6124
6125 static void
6126 resource_tree_free (ResTreeNode * node)
6127 {
6128         GSList * list;
6129         for (list = node->children; list; list = list->next)
6130                 resource_tree_free ((ResTreeNode*)list->data);
6131         g_slist_free(node->children);
6132         g_free (node);
6133 }
6134
6135 static void
6136 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6137 {
6138         char *buf;
6139         char *p;
6140         guint32 size, i;
6141         MonoReflectionWin32Resource *win32_res;
6142         ResTreeNode *tree;
6143
6144         if (!assemblyb->win32_resources)
6145                 return;
6146
6147         /*
6148          * Resources are stored in a three level tree inside the PE file.
6149          * - level one contains a node for each type of resource
6150          * - level two contains a node for each resource
6151          * - level three contains a node for each instance of a resource for a
6152          *   specific language.
6153          */
6154
6155         tree = resource_tree_create (assemblyb->win32_resources);
6156
6157         /* Estimate the size of the encoded tree */
6158         size = 0;
6159         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6160                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6161                 size += mono_array_length (win32_res->res_data);
6162         }
6163         /* Directory structure */
6164         size += mono_array_length (assemblyb->win32_resources) * 256;
6165         p = buf = (char *)g_malloc (size);
6166
6167         resource_tree_encode (tree, p, p, &p);
6168
6169         g_assert (p - buf <= size);
6170
6171         assembly->win32_res = (char *)g_malloc (p - buf);
6172         assembly->win32_res_size = p - buf;
6173         memcpy (assembly->win32_res, buf, p - buf);
6174
6175         g_free (buf);
6176         resource_tree_free (tree);
6177 }
6178
6179 static void
6180 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6181 {
6182         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6183         int i;
6184
6185         p += sizeof (MonoPEResourceDir);
6186         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6187                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6188                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6189                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6190                         fixup_resource_directory (res_section, child, rva);
6191                 } else {
6192                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6193                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6194                 }
6195
6196                 p += sizeof (MonoPEResourceDirEntry);
6197         }
6198 }
6199
6200 static void
6201 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6202 {
6203         guint32 dummy;
6204         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6205                 g_error ("WriteFile returned %d\n", GetLastError ());
6206 }
6207
6208 /*
6209  * mono_image_create_pefile:
6210  * @mb: a module builder object
6211  * 
6212  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6213  * assembly->pefile where it can be easily retrieved later in chunks.
6214  */
6215 gboolean
6216 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6217 {
6218         MonoMSDOSHeader *msdos;
6219         MonoDotNetHeader *header;
6220         MonoSectionTable *section;
6221         MonoCLIHeader *cli_header;
6222         guint32 size, image_size, virtual_base, text_offset;
6223         guint32 header_start, section_start, file_offset, virtual_offset;
6224         MonoDynamicImage *assembly;
6225         MonoReflectionAssemblyBuilder *assemblyb;
6226         MonoDynamicStream pefile_stream = {0};
6227         MonoDynamicStream *pefile = &pefile_stream;
6228         int i, nsections;
6229         guint32 *rva, value;
6230         guchar *p;
6231         static const unsigned char msheader[] = {
6232                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6233                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6234                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6235                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6236                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6237                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6238                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6239                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6240         };
6241
6242         mono_error_init (error);
6243
6244         assemblyb = mb->assemblyb;
6245
6246         mono_image_basic_init (assemblyb);
6247         assembly = mb->dynamic_image;
6248
6249         assembly->pe_kind = assemblyb->pe_kind;
6250         assembly->machine = assemblyb->machine;
6251         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6252         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6253         
6254         if (!mono_image_build_metadata (mb, error))
6255                 return FALSE;
6256         
6257
6258         if (mb->is_main && assemblyb->resources) {
6259                 int len = mono_array_length (assemblyb->resources);
6260                 for (i = 0; i < len; ++i)
6261                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6262         }
6263
6264         if (mb->resources) {
6265                 int len = mono_array_length (mb->resources);
6266                 for (i = 0; i < len; ++i)
6267                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6268         }
6269
6270         if (!build_compressed_metadata (assembly, error))
6271                 return FALSE;
6272
6273         if (mb->is_main)
6274                 assembly_add_win32_resources (assembly, assemblyb);
6275
6276         nsections = calc_section_size (assembly);
6277         
6278         /* The DOS header and stub */
6279         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6280         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6281
6282         /* the dotnet header */
6283         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6284
6285         /* the section tables */
6286         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6287
6288         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6289         virtual_offset = VIRT_ALIGN;
6290         image_size = 0;
6291
6292         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6293                 if (!assembly->sections [i].size)
6294                         continue;
6295                 /* align offsets */
6296                 file_offset += FILE_ALIGN - 1;
6297                 file_offset &= ~(FILE_ALIGN - 1);
6298                 virtual_offset += VIRT_ALIGN - 1;
6299                 virtual_offset &= ~(VIRT_ALIGN - 1);
6300
6301                 assembly->sections [i].offset = file_offset;
6302                 assembly->sections [i].rva = virtual_offset;
6303
6304                 file_offset += assembly->sections [i].size;
6305                 virtual_offset += assembly->sections [i].size;
6306                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6307         }
6308
6309         file_offset += FILE_ALIGN - 1;
6310         file_offset &= ~(FILE_ALIGN - 1);
6311
6312         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6313
6314         /* back-patch info */
6315         msdos = (MonoMSDOSHeader*)pefile->data;
6316         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6317
6318         header = (MonoDotNetHeader*)(pefile->data + header_start);
6319         header->pesig [0] = 'P';
6320         header->pesig [1] = 'E';
6321         
6322         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6323         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6324         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6325         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6326         if (assemblyb->pekind == 1) {
6327                 /* it's a dll */
6328                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6329         } else {
6330                 /* it's an exe */
6331                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6332         }
6333
6334         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6335
6336         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6337         header->pe.pe_major = 6;
6338         header->pe.pe_minor = 0;
6339         size = assembly->sections [MONO_SECTION_TEXT].size;
6340         size += FILE_ALIGN - 1;
6341         size &= ~(FILE_ALIGN - 1);
6342         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6343         size = assembly->sections [MONO_SECTION_RSRC].size;
6344         size += FILE_ALIGN - 1;
6345         size &= ~(FILE_ALIGN - 1);
6346         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6347         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6348         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6349         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6350         /* pe_rva_entry_point always at the beginning of the text section */
6351         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6352
6353         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6354         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6355         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6356         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6357         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6358         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6359         size = section_start;
6360         size += FILE_ALIGN - 1;
6361         size &= ~(FILE_ALIGN - 1);
6362         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6363         size = image_size;
6364         size += VIRT_ALIGN - 1;
6365         size &= ~(VIRT_ALIGN - 1);
6366         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6367
6368         /*
6369         // Translate the PEFileKind value to the value expected by the Windows loader
6370         */
6371         {
6372                 short kind;
6373
6374                 /*
6375                 // PEFileKinds.Dll == 1
6376                 // PEFileKinds.ConsoleApplication == 2
6377                 // PEFileKinds.WindowApplication == 3
6378                 //
6379                 // need to get:
6380                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6381                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6382                 */
6383                 if (assemblyb->pekind == 3)
6384                         kind = 2;
6385                 else
6386                         kind = 3;
6387                 
6388                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6389         }    
6390         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6391         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6392         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6393         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6394         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6395         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6396
6397         /* fill data directory entries */
6398
6399         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6400         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6401
6402         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6403         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6404
6405         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6406         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6407         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6408         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6409         /* patch entrypoint name */
6410         if (assemblyb->pekind == 1)
6411                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6412         else
6413                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6414         /* patch imported function RVA name */
6415         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6416         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6417
6418         /* the import table */
6419         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6420         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6421         /* patch imported dll RVA name and other entries in the dir */
6422         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6423         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6424         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6425         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6426         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6427         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6428
6429         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6430         value = (assembly->text_rva + assembly->imp_names_offset);
6431         *p++ = (value) & 0xff;
6432         *p++ = (value >> 8) & (0xff);
6433         *p++ = (value >> 16) & (0xff);
6434         *p++ = (value >> 24) & (0xff);
6435
6436         /* the CLI header info */
6437         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6438         cli_header->ch_size = GUINT32_FROM_LE (72);
6439         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6440         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6441         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6442         if (assemblyb->entry_point) {
6443                 guint32 table_idx = 0;
6444                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6445                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6446                         table_idx = methodb->table_idx;
6447                 } else {
6448                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6449                 }
6450                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6451         } else {
6452                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6453         }
6454         /* The embedded managed resources */
6455         text_offset = assembly->text_rva + assembly->code.index;
6456         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6457         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6458         text_offset += assembly->resources.index;
6459         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6460         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6461         text_offset += assembly->meta_size;
6462         if (assembly->strong_name_size) {
6463                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6464                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6465                 text_offset += assembly->strong_name_size;
6466         }
6467
6468         /* write the section tables and section content */
6469         section = (MonoSectionTable*)(pefile->data + section_start);
6470         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6471                 static const char section_names [][7] = {
6472                         ".text", ".rsrc", ".reloc"
6473                 };
6474                 if (!assembly->sections [i].size)
6475                         continue;
6476                 strcpy (section->st_name, section_names [i]);
6477                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6478                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6479                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6480                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6481                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6482                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6483                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6484                 section ++;
6485         }
6486         
6487         checked_write_file (file, pefile->data, pefile->index);
6488         
6489         mono_dynamic_stream_reset (pefile);
6490         
6491         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6492                 if (!assembly->sections [i].size)
6493                         continue;
6494                 
6495                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6496                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6497                 
6498                 switch (i) {
6499                 case MONO_SECTION_TEXT:
6500                         /* patch entry point */
6501                         p = (guchar*)(assembly->code.data + 2);
6502                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6503                         *p++ = (value) & 0xff;
6504                         *p++ = (value >> 8) & 0xff;
6505                         *p++ = (value >> 16) & 0xff;
6506                         *p++ = (value >> 24) & 0xff;
6507                 
6508                         checked_write_file (file, assembly->code.data, assembly->code.index);
6509                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6510                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6511                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6512                                 
6513
6514                         g_free (assembly->image.raw_metadata);
6515                         break;
6516                 case MONO_SECTION_RELOC: {
6517                         struct {
6518                                 guint32 page_rva;
6519                                 guint32 block_size;
6520                                 guint16 type_and_offset;
6521                                 guint16 term;
6522                         } reloc;
6523                         
6524                         g_assert (sizeof (reloc) == 12);
6525                         
6526                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6527                         reloc.block_size = GUINT32_FROM_LE (12);
6528                         
6529                         /* 
6530                          * the entrypoint is always at the start of the text section 
6531                          * 3 is IMAGE_REL_BASED_HIGHLOW
6532                          * 2 is patch_size_rva - text_rva
6533                          */
6534                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6535                         reloc.term = 0;
6536                         
6537                         checked_write_file (file, &reloc, sizeof (reloc));
6538                         
6539                         break;
6540                 }
6541                 case MONO_SECTION_RSRC:
6542                         if (assembly->win32_res) {
6543
6544                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6545                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6546                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6547                         }
6548                         break;
6549                 default:
6550                         g_assert_not_reached ();
6551                 }
6552         }
6553         
6554         /* check that the file is properly padded */
6555         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6556                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6557         if (! SetEndOfFile (file))
6558                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6559         
6560         mono_dynamic_stream_reset (&assembly->code);
6561         mono_dynamic_stream_reset (&assembly->us);
6562         mono_dynamic_stream_reset (&assembly->blob);
6563         mono_dynamic_stream_reset (&assembly->guid);
6564         mono_dynamic_stream_reset (&assembly->sheap);
6565
6566         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6567         g_hash_table_destroy (assembly->blob_cache);
6568         assembly->blob_cache = NULL;
6569
6570         return TRUE;
6571 }
6572
6573 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6574
6575 gboolean
6576 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6577 {
6578         g_assert_not_reached ();
6579 }
6580
6581 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6582
6583 #ifndef DISABLE_REFLECTION_EMIT
6584
6585 MonoReflectionModule *
6586 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6587 {
6588         MonoError error;
6589         MonoReflectionModule *result = NULL;
6590         char *name;
6591         MonoImage *image;
6592         MonoImageOpenStatus status;
6593         MonoDynamicAssembly *assembly;
6594         guint32 module_count;
6595         MonoImage **new_modules;
6596         gboolean *new_modules_loaded;
6597         
6598         name = mono_string_to_utf8 (fileName);
6599
6600         image = mono_image_open (name, &status);
6601         if (!image) {
6602                 MonoException *exc;
6603                 if (status == MONO_IMAGE_ERROR_ERRNO)
6604                         exc = mono_get_exception_file_not_found (fileName);
6605                 else
6606                         exc = mono_get_exception_bad_image_format (name);
6607                 g_free (name);
6608                 mono_raise_exception (exc);
6609         }
6610
6611         g_free (name);
6612
6613         assembly = ab->dynamic_assembly;
6614         image->assembly = (MonoAssembly*)assembly;
6615
6616         module_count = image->assembly->image->module_count;
6617         new_modules = g_new0 (MonoImage *, module_count + 1);
6618         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6619
6620         if (image->assembly->image->modules)
6621                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6622         if (image->assembly->image->modules_loaded)
6623                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6624         new_modules [module_count] = image;
6625         new_modules_loaded [module_count] = TRUE;
6626         mono_image_addref (image);
6627
6628         g_free (image->assembly->image->modules);
6629         image->assembly->image->modules = new_modules;
6630         image->assembly->image->modules_loaded = new_modules_loaded;
6631         image->assembly->image->module_count ++;
6632
6633         mono_assembly_load_references (image, &status);
6634         if (status) {
6635                 mono_image_close (image);
6636                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6637         }
6638
6639         result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6640         mono_error_raise_exception (&error); /* FIXME don't raise here */
6641         return result;
6642 }
6643
6644 #endif /* DISABLE_REFLECTION_EMIT */
6645
6646 /*
6647  * We need to return always the same object for MethodInfo, FieldInfo etc..
6648  * but we need to consider the reflected type.
6649  * type uses a different hash, since it uses custom hash/equal functions.
6650  */
6651
6652 typedef struct {
6653         gpointer item;
6654         MonoClass *refclass;
6655 } ReflectedEntry;
6656
6657 static gboolean
6658 reflected_equal (gconstpointer a, gconstpointer b) {
6659         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6660         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6661
6662         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6663 }
6664
6665 static guint
6666 reflected_hash (gconstpointer a) {
6667         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6668         return mono_aligned_addr_hash (ea->item);
6669 }
6670
6671 #define CHECK_OBJECT(t,p,k)     \
6672         do {    \
6673                 t _obj; \
6674                 ReflectedEntry e;       \
6675                 e.item = (p);   \
6676                 e.refclass = (k);       \
6677                 mono_domain_lock (domain);      \
6678                 if (!domain->refobject_hash)    \
6679                         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");  \
6680                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6681                         mono_domain_unlock (domain);    \
6682                         return _obj;    \
6683                 }       \
6684         mono_domain_unlock (domain); \
6685         } while (0)
6686
6687 #ifdef HAVE_BOEHM_GC
6688 /* ReflectedEntry doesn't need to be GC tracked */
6689 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6690 #define FREE_REFENTRY(entry) g_free ((entry))
6691 #define REFENTRY_REQUIRES_CLEANUP
6692 #else
6693 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6694 /* FIXME: */
6695 #define FREE_REFENTRY(entry)
6696 #endif
6697
6698 #define CACHE_OBJECT(t,p,o,k)   \
6699         do {    \
6700                 t _obj; \
6701         ReflectedEntry pe; \
6702         pe.item = (p); \
6703         pe.refclass = (k); \
6704         mono_domain_lock (domain); \
6705                 if (!domain->refobject_hash)    \
6706                         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");  \
6707         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6708         if (!_obj) { \
6709                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6710                     e->item = (p);      \
6711                     e->refclass = (k);  \
6712                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6713             _obj = o; \
6714         } \
6715                 mono_domain_unlock (domain);    \
6716         return _obj; \
6717         } while (0)
6718
6719 static void
6720 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6721 {
6722         mono_domain_lock (domain);
6723         if (domain->refobject_hash) {
6724         ReflectedEntry pe;
6725                 gpointer orig_pe, orig_value;
6726
6727                 pe.item = o;
6728                 pe.refclass = klass;
6729                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6730                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6731                         FREE_REFENTRY (orig_pe);
6732                 }
6733         }
6734         mono_domain_unlock (domain);
6735 }
6736
6737 #ifdef REFENTRY_REQUIRES_CLEANUP
6738 static void
6739 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6740 {
6741         FREE_REFENTRY (key);
6742 }
6743 #endif
6744
6745 void
6746 mono_reflection_cleanup_domain (MonoDomain *domain)
6747 {
6748         if (domain->refobject_hash) {
6749 /*let's avoid scanning the whole hashtable if not needed*/
6750 #ifdef REFENTRY_REQUIRES_CLEANUP
6751                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6752 #endif
6753                 mono_g_hash_table_destroy (domain->refobject_hash);
6754                 domain->refobject_hash = NULL;
6755         }
6756 }
6757
6758 #ifndef DISABLE_REFLECTION_EMIT
6759 static gpointer
6760 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6761 {
6762         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6763 }
6764
6765 static gpointer
6766 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6767 {
6768         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6769 }
6770
6771 void
6772 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6773 {
6774         MonoDynamicImage *image = moduleb->dynamic_image;
6775         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6776         if (!image) {
6777                 MonoError error;
6778                 int module_count;
6779                 MonoImage **new_modules;
6780                 MonoImage *ass;
6781                 char *name, *fqname;
6782                 /*
6783                  * FIXME: we already created an image in mono_image_basic_init (), but
6784                  * we don't know which module it belongs to, since that is only 
6785                  * determined at assembly save time.
6786                  */
6787                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6788                 name = mono_string_to_utf8 (ab->name);
6789                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6790                 if (!mono_error_ok (&error)) {
6791                         g_free (name);
6792                         mono_error_raise_exception (&error);
6793                 }
6794                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6795
6796                 moduleb->module.image = &image->image;
6797                 moduleb->dynamic_image = image;
6798                 register_module (mono_object_domain (moduleb), moduleb, image);
6799
6800                 /* register the module with the assembly */
6801                 ass = ab->dynamic_assembly->assembly.image;
6802                 module_count = ass->module_count;
6803                 new_modules = g_new0 (MonoImage *, module_count + 1);
6804
6805                 if (ass->modules)
6806                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6807                 new_modules [module_count] = &image->image;
6808                 mono_image_addref (&image->image);
6809
6810                 g_free (ass->modules);
6811                 ass->modules = new_modules;
6812                 ass->module_count ++;
6813         }
6814 }
6815
6816 void
6817 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6818 {
6819         MonoDynamicImage *image = moduleb->dynamic_image;
6820
6821         g_assert (type->type);
6822         image->wrappers_type = mono_class_from_mono_type (type->type);
6823 }
6824
6825 #endif
6826
6827 /*
6828  * mono_assembly_get_object:
6829  * @domain: an app domain
6830  * @assembly: an assembly
6831  *
6832  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6833  */
6834 MonoReflectionAssembly*
6835 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6836 {
6837         MonoError error;
6838         MonoReflectionAssembly *result;
6839         result = mono_assembly_get_object_checked (domain, assembly, &error);
6840         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6841         return result;
6842 }
6843 /*
6844  * mono_assembly_get_object_checked:
6845  * @domain: an app domain
6846  * @assembly: an assembly
6847  *
6848  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6849  */
6850 MonoReflectionAssembly*
6851 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6852 {
6853         MonoReflectionAssembly *res;
6854         
6855         mono_error_init (error);
6856
6857         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6858         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6859         if (!res)
6860                 return NULL;
6861         res->assembly = assembly;
6862
6863         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6864 }
6865
6866
6867
6868 MonoReflectionModule*   
6869 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6870 {
6871         MonoError error;
6872         MonoReflectionModule *result;
6873         result = mono_module_get_object_checked (domain, image, &error);
6874         mono_error_raise_exception (&error);
6875         return result;
6876 }
6877
6878 MonoReflectionModule*
6879 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6880 {
6881         MonoReflectionModule *res;
6882         char* basename;
6883         
6884         mono_error_init (error);
6885         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6886         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6887         if (!res)
6888                 return NULL;
6889
6890         res->image = image;
6891         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6892         if (!assm_obj)
6893                 return NULL;
6894         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6895
6896         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6897         basename = g_path_get_basename (image->name);
6898         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6899         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6900         
6901         g_free (basename);
6902
6903         if (image->assembly->image == image) {
6904                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6905         } else {
6906                 int i;
6907                 res->token = 0;
6908                 if (image->assembly->image->modules) {
6909                         for (i = 0; i < image->assembly->image->module_count; i++) {
6910                                 if (image->assembly->image->modules [i] == image)
6911                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6912                         }
6913                         g_assert (res->token);
6914                 }
6915         }
6916
6917         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6918 }
6919
6920 MonoReflectionModule*
6921 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6922 {
6923         MonoError error;
6924         MonoReflectionModule *result;
6925         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6926         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6927         return result;
6928 }
6929
6930 MonoReflectionModule*
6931 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6932 {
6933         MonoReflectionModule *res;
6934         MonoTableInfo *table;
6935         guint32 cols [MONO_FILE_SIZE];
6936         const char *name;
6937         guint32 i, name_idx;
6938         const char *val;
6939         
6940         mono_error_init (error);
6941
6942         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6943         if (!res)
6944                 return NULL;
6945
6946         table = &image->tables [MONO_TABLE_FILE];
6947         g_assert (table_index < table->rows);
6948         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6949
6950         res->image = NULL;
6951         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6952         if (!assm_obj)
6953                 return NULL;
6954         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6955         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6956
6957         /* Check whenever the row has a corresponding row in the moduleref table */
6958         table = &image->tables [MONO_TABLE_MODULEREF];
6959         for (i = 0; i < table->rows; ++i) {
6960                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6961                 val = mono_metadata_string_heap (image, name_idx);
6962                 if (strcmp (val, name) == 0)
6963                         res->image = image->modules [i];
6964         }
6965
6966         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6967         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6968         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6969         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6970         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6971
6972         return res;
6973 }
6974
6975 static gboolean
6976 verify_safe_for_managed_space (MonoType *type)
6977 {
6978         switch (type->type) {
6979 #ifdef DEBUG_HARDER
6980         case MONO_TYPE_ARRAY:
6981                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6982         case MONO_TYPE_PTR:
6983                 return verify_safe_for_managed_space (type->data.type);
6984         case MONO_TYPE_SZARRAY:
6985                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6986         case MONO_TYPE_GENERICINST: {
6987                 MonoGenericInst *inst = type->data.generic_class->inst;
6988                 int i;
6989                 if (!inst->is_open)
6990                         break;
6991                 for (i = 0; i < inst->type_argc; ++i)
6992                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6993                                 return FALSE;
6994                 return TRUE;
6995         }
6996 #endif
6997         case MONO_TYPE_VAR:
6998         case MONO_TYPE_MVAR:
6999                 return TRUE;
7000         default:
7001                 return TRUE;
7002         }
7003 }
7004
7005 static MonoType*
7006 mono_type_normalize (MonoType *type)
7007 {
7008         int i;
7009         MonoGenericClass *gclass;
7010         MonoGenericInst *ginst;
7011         MonoClass *gtd;
7012         MonoGenericContainer *gcontainer;
7013         MonoType **argv = NULL;
7014         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7015
7016         if (type->type != MONO_TYPE_GENERICINST)
7017                 return type;
7018
7019         gclass = type->data.generic_class;
7020         ginst = gclass->context.class_inst;
7021         if (!ginst->is_open)
7022                 return type;
7023
7024         gtd = gclass->container_class;
7025         gcontainer = gtd->generic_container;
7026         argv = g_newa (MonoType*, ginst->type_argc);
7027
7028         for (i = 0; i < ginst->type_argc; ++i) {
7029                 MonoType *t = ginst->type_argv [i], *norm;
7030                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7031                         is_denorm_gtd = FALSE;
7032                 norm = mono_type_normalize (t);
7033                 argv [i] = norm;
7034                 if (norm != t)
7035                         requires_rebind = TRUE;
7036         }
7037
7038         if (is_denorm_gtd)
7039                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7040
7041         if (requires_rebind) {
7042                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7043                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7044         }
7045
7046         return type;
7047 }
7048 /*
7049  * mono_type_get_object:
7050  * @domain: an app domain
7051  * @type: a type
7052  *
7053  * Return an System.MonoType object representing the type @type.
7054  */
7055 MonoReflectionType*
7056 mono_type_get_object (MonoDomain *domain, MonoType *type)
7057 {
7058         MonoError error;
7059         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7060         mono_error_raise_exception (&error);
7061
7062         return ret;
7063 }
7064
7065 MonoReflectionType*
7066 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7067 {
7068         MonoType *norm_type;
7069         MonoReflectionType *res;
7070         MonoClass *klass;
7071
7072         mono_error_init (error);
7073
7074         klass = mono_class_from_mono_type (type);
7075
7076         /*we must avoid using @type as it might have come
7077          * from a mono_metadata_type_dup and the caller
7078          * expects that is can be freed.
7079          * Using the right type from 
7080          */
7081         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7082
7083         /* void is very common */
7084         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7085                 return (MonoReflectionType*)domain->typeof_void;
7086
7087         /*
7088          * If the vtable of the given class was already created, we can use
7089          * the MonoType from there and avoid all locking and hash table lookups.
7090          * 
7091          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7092          * that the resulting object is different.   
7093          */
7094         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7095                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7096                 if (vtable && vtable->type)
7097                         return (MonoReflectionType *)vtable->type;
7098         }
7099
7100         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7101         mono_domain_lock (domain);
7102         if (!domain->type_hash)
7103                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7104                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7105         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7106                 mono_domain_unlock (domain);
7107                 mono_loader_unlock ();
7108                 return res;
7109         }
7110
7111         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7112          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7113          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7114          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7115          * artifact of how generics are encoded and should be transparent to managed code so we
7116          * need to weed out this diference when retrieving managed System.Type objects.
7117          */
7118         norm_type = mono_type_normalize (type);
7119         if (norm_type != type) {
7120                 res = mono_type_get_object_checked (domain, norm_type, error);
7121                 if (!mono_error_ok (error))
7122                         return NULL;
7123                 mono_g_hash_table_insert (domain->type_hash, type, res);
7124                 mono_domain_unlock (domain);
7125                 mono_loader_unlock ();
7126                 return res;
7127         }
7128
7129         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7130         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7131                 g_assert (0);
7132
7133         if (!verify_safe_for_managed_space (type)) {
7134                 mono_domain_unlock (domain);
7135                 mono_loader_unlock ();
7136                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7137                 return NULL;
7138         }
7139
7140         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7141                 gboolean is_type_done = TRUE;
7142                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7143                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7144                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7145                 */
7146                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7147                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7148
7149                         if (gparam->owner && gparam->owner->is_method) {
7150                                 MonoMethod *method = gparam->owner->owner.method;
7151                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7152                                         is_type_done = FALSE;
7153                         } else if (gparam->owner && !gparam->owner->is_method) {
7154                                 MonoClass *klass = gparam->owner->owner.klass;
7155                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7156                                         is_type_done = FALSE;
7157                         }
7158                 } 
7159
7160                 /* g_assert_not_reached (); */
7161                 /* should this be considered an error condition? */
7162                 if (is_type_done && !type->byref) {
7163                         mono_domain_unlock (domain);
7164                         mono_loader_unlock ();
7165                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7166                 }
7167         }
7168         /* This is stored in vtables/JITted code so it has to be pinned */
7169         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7170         if (!mono_error_ok (error))
7171                 return NULL;
7172
7173         res->type = type;
7174         mono_g_hash_table_insert (domain->type_hash, type, res);
7175
7176         if (type->type == MONO_TYPE_VOID)
7177                 domain->typeof_void = (MonoObject*)res;
7178
7179         mono_domain_unlock (domain);
7180         mono_loader_unlock ();
7181         return res;
7182 }
7183
7184 /*
7185  * mono_method_get_object:
7186  * @domain: an app domain
7187  * @method: a method
7188  * @refclass: the reflected type (can be NULL)
7189  *
7190  * Return an System.Reflection.MonoMethod object representing the method @method.
7191  */
7192 MonoReflectionMethod*
7193 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7194 {
7195         MonoError error;
7196         MonoReflectionMethod *ret = NULL;
7197         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7198         mono_error_raise_exception (&error);
7199         return ret;
7200 }
7201
7202 /*
7203  * mono_method_get_object_checked:
7204  * @domain: an app domain
7205  * @method: a method
7206  * @refclass: the reflected type (can be NULL)
7207  * @error: set on error.
7208  *
7209  * Return an System.Reflection.MonoMethod object representing the method @method.
7210  * Returns NULL and sets @error on error.
7211  */
7212 MonoReflectionMethod*
7213 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7214 {
7215         /*
7216          * We use the same C representation for methods and constructors, but the type 
7217          * name in C# is different.
7218          */
7219         MonoReflectionType *rt;
7220         MonoClass *klass;
7221         MonoReflectionMethod *ret;
7222
7223         mono_error_init (error);
7224
7225         if (method->is_inflated) {
7226                 MonoReflectionGenericMethod *gret;
7227
7228                 if (!refclass)
7229                         refclass = method->klass;
7230                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7231                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7232                         klass = mono_class_get_mono_generic_cmethod_class ();
7233                 } else {
7234                         klass = mono_class_get_mono_generic_method_class ();
7235                 }
7236                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7237                 if (!mono_error_ok (error))
7238                         goto leave;
7239                 gret->method.method = method;
7240
7241                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7242
7243                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7244                 if (!mono_error_ok (error))
7245                     goto leave;
7246
7247                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7248
7249                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7250         }
7251
7252         if (!refclass)
7253                 refclass = method->klass;
7254
7255         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7256         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7257                 klass = mono_class_get_mono_cmethod_class ();
7258         }
7259         else {
7260                 klass = mono_class_get_mono_method_class ();
7261         }
7262         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7263         if (!mono_error_ok (error))
7264                 goto leave;
7265         ret->method = method;
7266
7267         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7268         if (!mono_error_ok (error))
7269                 goto leave;
7270
7271         MONO_OBJECT_SETREF (ret, reftype, rt);
7272
7273         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7274
7275 leave:
7276         g_assert (!mono_error_ok (error));
7277         return NULL;
7278 }
7279
7280 /*
7281  * mono_method_clear_object:
7282  *
7283  *   Clear the cached reflection objects for the dynamic method METHOD.
7284  */
7285 void
7286 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7287 {
7288         MonoClass *klass;
7289         g_assert (method_is_dynamic (method));
7290
7291         klass = method->klass;
7292         while (klass) {
7293                 clear_cached_object (domain, method, klass);
7294                 klass = klass->parent;
7295         }
7296         /* Added by mono_param_get_objects () */
7297         clear_cached_object (domain, &(method->signature), NULL);
7298         klass = method->klass;
7299         while (klass) {
7300                 clear_cached_object (domain, &(method->signature), klass);
7301                 klass = klass->parent;
7302         }
7303 }
7304
7305 /*
7306  * mono_field_get_object:
7307  * @domain: an app domain
7308  * @klass: a type
7309  * @field: a field
7310  *
7311  * Return an System.Reflection.MonoField object representing the field @field
7312  * in class @klass.
7313  */
7314 MonoReflectionField*
7315 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7316 {
7317         MonoError error;
7318         MonoReflectionField *result;
7319         result = mono_field_get_object_checked (domain, klass, field, &error);
7320         mono_error_raise_exception (&error);
7321         return result;
7322 }
7323
7324 /*
7325  * mono_field_get_object_checked:
7326  * @domain: an app domain
7327  * @klass: a type
7328  * @field: a field
7329  * @error: set on error
7330  *
7331  * Return an System.Reflection.MonoField object representing the field @field
7332  * in class @klass. On error, returns NULL and sets @error.
7333  */
7334 MonoReflectionField*
7335 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7336 {
7337         MonoReflectionType *rt;
7338         MonoReflectionField *res;
7339
7340         mono_error_init (error);
7341
7342         CHECK_OBJECT (MonoReflectionField *, field, klass);
7343         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7344         if (!res)
7345                 return NULL;
7346         res->klass = klass;
7347         res->field = field;
7348         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7349
7350         if (is_field_on_inst (field)) {
7351                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7352
7353                 rt = mono_type_get_object_checked (domain, field->type, error);
7354                 if (!mono_error_ok (error))
7355                         return NULL;
7356
7357                 MONO_OBJECT_SETREF (res, type, rt);
7358         } else {
7359                 if (field->type) {
7360                         rt = mono_type_get_object_checked (domain, field->type, error);
7361                         if (!mono_error_ok (error))
7362                                 return NULL;
7363
7364                         MONO_OBJECT_SETREF (res, type, rt);
7365                 }
7366                 res->attrs = mono_field_get_flags (field);
7367         }
7368         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7369 }
7370
7371 /*
7372  * mono_property_get_object:
7373  * @domain: an app domain
7374  * @klass: a type
7375  * @property: a property
7376  *
7377  * Return an System.Reflection.MonoProperty object representing the property @property
7378  * in class @klass.
7379  */
7380 MonoReflectionProperty*
7381 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7382 {
7383         MonoError error;
7384         MonoReflectionProperty *result;
7385         result = mono_property_get_object_checked (domain, klass, property, &error);
7386         mono_error_raise_exception (&error);
7387         return result;
7388 }
7389
7390 /**
7391  * mono_property_get_object:
7392  * @domain: an app domain
7393  * @klass: a type
7394  * @property: a property
7395  * @error: set on error
7396  *
7397  * Return an System.Reflection.MonoProperty object representing the property @property
7398  * in class @klass.  On error returns NULL and sets @error.
7399  */
7400 MonoReflectionProperty*
7401 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7402 {
7403         MonoReflectionProperty *res;
7404
7405         mono_error_init (error);
7406
7407         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7408         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7409         if (!res)
7410                 return NULL;
7411         res->klass = klass;
7412         res->property = property;
7413         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7414 }
7415
7416 /*
7417  * mono_event_get_object:
7418  * @domain: an app domain
7419  * @klass: a type
7420  * @event: a event
7421  *
7422  * Return an System.Reflection.MonoEvent object representing the event @event
7423  * in class @klass.
7424  */
7425 MonoReflectionEvent*
7426 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7427 {
7428         MonoError error;
7429         MonoReflectionEvent *result;
7430         result = mono_event_get_object_checked (domain, klass, event, &error);
7431         mono_error_raise_exception (&error);
7432         return result;
7433 }
7434
7435 /**
7436  * mono_event_get_object_checked:
7437  * @domain: an app domain
7438  * @klass: a type
7439  * @event: a event
7440  * @error: set on error
7441  *
7442  * Return an System.Reflection.MonoEvent object representing the event @event
7443  * in class @klass. On failure sets @error and returns NULL
7444  */
7445 MonoReflectionEvent*
7446 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7447 {
7448         MonoReflectionEvent *res;
7449         MonoReflectionMonoEvent *mono_event;
7450
7451         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7452         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7453         if (!mono_event)
7454                 return NULL;
7455         mono_event->klass = klass;
7456         mono_event->event = event;
7457         res = (MonoReflectionEvent*)mono_event;
7458         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7459 }
7460
7461 /**
7462  * mono_get_reflection_missing_object:
7463  * @domain: Domain where the object lives
7464  *
7465  * Returns the System.Reflection.Missing.Value singleton object
7466  * (of type System.Reflection.Missing).
7467  *
7468  * Used as the value for ParameterInfo.DefaultValue when Optional
7469  * is present
7470  */
7471 static MonoObject *
7472 mono_get_reflection_missing_object (MonoDomain *domain)
7473 {
7474         MonoObject *obj;
7475         static MonoClassField *missing_value_field = NULL;
7476         
7477         if (!missing_value_field) {
7478                 MonoClass *missing_klass;
7479                 missing_klass = mono_class_get_missing_class ();
7480                 mono_class_init (missing_klass);
7481                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7482                 g_assert (missing_value_field);
7483         }
7484         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7485         g_assert (obj);
7486         return obj;
7487 }
7488
7489 static MonoObject*
7490 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7491 {
7492         if (!*dbnull)
7493                 *dbnull = mono_get_dbnull_object (domain);
7494         return *dbnull;
7495 }
7496
7497 static MonoObject*
7498 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7499 {
7500         if (!*reflection_missing)
7501                 *reflection_missing = mono_get_reflection_missing_object (domain);
7502         return *reflection_missing;
7503 }
7504
7505 /*
7506  * mono_param_get_objects:
7507  * @domain: an app domain
7508  * @method: a method
7509  *
7510  * Return an System.Reflection.ParameterInfo array object representing the parameters
7511  * in the method @method.
7512  */
7513 MonoArray*
7514 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7515 {
7516         static MonoClass *System_Reflection_ParameterInfo;
7517         static MonoClass *System_Reflection_ParameterInfo_array;
7518         MonoError error;
7519         MonoArray *res = NULL;
7520         MonoReflectionMethod *member = NULL;
7521         MonoReflectionParameter *param = NULL;
7522         char **names = NULL, **blobs = NULL;
7523         guint32 *types = NULL;
7524         MonoType *type = NULL;
7525         MonoObject *dbnull = NULL;
7526         MonoObject *missing = NULL;
7527         MonoMarshalSpec **mspecs = NULL;
7528         MonoMethodSignature *sig = NULL;
7529         MonoVTable *pinfo_vtable;
7530         MonoReflectionType *rt;
7531         int i;
7532
7533         mono_error_init (&error);
7534         
7535         if (!System_Reflection_ParameterInfo_array) {
7536                 MonoClass *klass;
7537
7538                 klass = mono_class_get_mono_parameter_info_class ();
7539
7540                 mono_memory_barrier ();
7541                 System_Reflection_ParameterInfo = klass; 
7542
7543         
7544                 klass = mono_array_class_get (klass, 1);
7545                 mono_memory_barrier ();
7546                 System_Reflection_ParameterInfo_array = klass;
7547         }
7548
7549         sig = mono_method_signature_checked (method, &error);
7550         if (!mono_error_ok (&error))
7551                 goto leave;
7552
7553         if (!sig->param_count) {
7554                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7555                 if (!res)
7556                         goto leave;
7557
7558                 return res;
7559         }
7560
7561         /* Note: the cache is based on the address of the signature into the method
7562          * since we already cache MethodInfos with the method as keys.
7563          */
7564         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7565
7566         member = mono_method_get_object_checked (domain, method, refclass, &error);
7567         if (!member)
7568                 goto leave;
7569         names = g_new (char *, sig->param_count);
7570         mono_method_get_param_names (method, (const char **) names);
7571
7572         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7573         mono_method_get_marshal_info (method, mspecs);
7574
7575         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7576         if (!res)
7577                 goto leave;
7578
7579         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7580         for (i = 0; i < sig->param_count; ++i) {
7581                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7582                 if (!param)
7583                         goto leave;
7584
7585                 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7586                 if (!rt)
7587                         goto leave;
7588
7589                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7590
7591                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7592
7593                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7594
7595                 param->PositionImpl = i;
7596                 param->AttrsImpl = sig->params [i]->attrs;
7597
7598                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7599                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7600                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7601                         else
7602                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7603                 } else {
7604
7605                         if (!blobs) {
7606                                 blobs = g_new0 (char *, sig->param_count);
7607                                 types = g_new0 (guint32, sig->param_count);
7608                                 get_default_param_value_blobs (method, blobs, types); 
7609                         }
7610
7611                         /* Build MonoType for the type from the Constant Table */
7612                         if (!type)
7613                                 type = g_new0 (MonoType, 1);
7614                         type->type = (MonoTypeEnum)types [i];
7615                         type->data.klass = NULL;
7616                         if (types [i] == MONO_TYPE_CLASS)
7617                                 type->data.klass = mono_defaults.object_class;
7618                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7619                                 /* For enums, types [i] contains the base type */
7620
7621                                         type->type = MONO_TYPE_VALUETYPE;
7622                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7623                         } else
7624                                 type->data.klass = mono_class_from_mono_type (type);
7625
7626                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7627
7628                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7629                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7630                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7631                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7632                                 else
7633                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7634                         }
7635                         
7636                 }
7637
7638                 if (mspecs [i + 1]) {
7639                         MonoReflectionMarshalAsAttribute* mobj;
7640                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7641                         if (!mobj)
7642                                 goto leave;
7643                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7644                 }
7645                 
7646                 mono_array_setref (res, i, param);
7647         }
7648
7649 leave:
7650         g_free (names);
7651         g_free (blobs);
7652         g_free (types);
7653         g_free (type);
7654
7655         if (sig) {
7656                 for (i = sig->param_count; i >= 0; i--) {
7657                         if (mspecs [i])
7658                                 mono_metadata_free_marshal_spec (mspecs [i]);
7659                 }
7660         }
7661         g_free (mspecs);
7662
7663         mono_error_raise_exception (&error); /* FIXME don't raise here */
7664         
7665         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7666 }
7667
7668 MonoArray*
7669 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7670 {
7671         return mono_param_get_objects_internal (domain, method, NULL);
7672 }
7673
7674 /*
7675  * mono_method_body_get_object:
7676  * @domain: an app domain
7677  * @method: a method
7678  *
7679  * Return an System.Reflection.MethodBody object representing the method @method.
7680  */
7681 MonoReflectionMethodBody*
7682 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7683 {
7684         MonoError error;
7685         MonoReflectionMethodBody *ret;
7686         MonoMethodHeader *header;
7687         MonoImage *image;
7688         MonoReflectionType *rt;
7689         guint32 method_rva, local_var_sig_token;
7690     char *ptr;
7691         unsigned char format, flags;
7692         int i;
7693
7694         /* for compatibility with .net */
7695     if (method_is_dynamic (method))
7696         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7697
7698         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7699
7700         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7701                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7702             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7703                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7704             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7705                 return NULL;
7706
7707         image = method->klass->image;
7708         header = mono_method_get_header_checked (method, &error);
7709         mono_error_raise_exception (&error); /* FIXME don't raise here */
7710
7711         if (!image_is_dynamic (image)) {
7712                 /* Obtain local vars signature token */
7713                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7714                 ptr = mono_image_rva_map (image, method_rva);
7715                 flags = *(const unsigned char *) ptr;
7716                 format = flags & METHOD_HEADER_FORMAT_MASK;
7717                 switch (format){
7718                 case METHOD_HEADER_TINY_FORMAT:
7719                         local_var_sig_token = 0;
7720                         break;
7721                 case METHOD_HEADER_FAT_FORMAT:
7722                         ptr += 2;
7723                         ptr += 2;
7724                         ptr += 4;
7725                         local_var_sig_token = read32 (ptr);
7726                         break;
7727                 default:
7728                         g_assert_not_reached ();
7729                 }
7730         } else
7731                 local_var_sig_token = 0; //FIXME
7732
7733         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7734         mono_error_raise_exception (&error); /* FIXME don't raise here */
7735
7736         ret->init_locals = header->init_locals;
7737         ret->max_stack = header->max_stack;
7738         ret->local_var_sig_token = local_var_sig_token;
7739         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7740         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7741
7742         /* Locals */
7743         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7744         for (i = 0; i < header->num_locals; ++i) {
7745                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7746                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7747
7748                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7749                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7750
7751                 MONO_OBJECT_SETREF (info, local_type, rt);
7752
7753                 info->is_pinned = header->locals [i]->pinned;
7754                 info->local_index = i;
7755                 mono_array_setref (ret->locals, i, info);
7756         }
7757
7758         /* Exceptions */
7759         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7760         for (i = 0; i < header->num_clauses; ++i) {
7761                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7762                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7763                 MonoExceptionClause *clause = &header->clauses [i];
7764
7765                 info->flags = clause->flags;
7766                 info->try_offset = clause->try_offset;
7767                 info->try_length = clause->try_len;
7768                 info->handler_offset = clause->handler_offset;
7769                 info->handler_length = clause->handler_len;
7770                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7771                         info->filter_offset = clause->data.filter_offset;
7772                 else if (clause->data.catch_class) {
7773                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7774                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7775
7776                         MONO_OBJECT_SETREF (info, catch_type, rt);
7777                 }
7778
7779                 mono_array_setref (ret->clauses, i, info);
7780         }
7781
7782         mono_metadata_free_mh (header);
7783         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7784         return ret;
7785 }
7786
7787 /**
7788  * mono_get_dbnull_object:
7789  * @domain: Domain where the object lives
7790  *
7791  * Returns the System.DBNull.Value singleton object
7792  *
7793  * Used as the value for ParameterInfo.DefaultValue 
7794  */
7795 MonoObject *
7796 mono_get_dbnull_object (MonoDomain *domain)
7797 {
7798         MonoObject *obj;
7799         static MonoClassField *dbnull_value_field = NULL;
7800         
7801         if (!dbnull_value_field) {
7802                 MonoClass *dbnull_klass;
7803                 dbnull_klass = mono_class_get_dbnull_class ();
7804                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7805                 g_assert (dbnull_value_field);
7806         }
7807         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7808         g_assert (obj);
7809         return obj;
7810 }
7811
7812 static void
7813 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7814 {
7815         guint32 param_index, i, lastp, crow = 0;
7816         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7817         gint32 idx;
7818
7819         MonoClass *klass = method->klass;
7820         MonoImage *image = klass->image;
7821         MonoMethodSignature *methodsig = mono_method_signature (method);
7822
7823         MonoTableInfo *constt;
7824         MonoTableInfo *methodt;
7825         MonoTableInfo *paramt;
7826
7827         if (!methodsig->param_count)
7828                 return;
7829
7830         mono_class_init (klass);
7831
7832         if (image_is_dynamic (klass->image)) {
7833                 MonoReflectionMethodAux *aux;
7834                 if (method->is_inflated)
7835                         method = ((MonoMethodInflated*)method)->declaring;
7836                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7837                 if (aux && aux->param_defaults) {
7838                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7839                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7840                 }
7841                 return;
7842         }
7843
7844         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7845         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7846         constt = &image->tables [MONO_TABLE_CONSTANT];
7847
7848         idx = mono_method_get_index (method) - 1;
7849         g_assert (idx != -1);
7850
7851         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7852         if (idx + 1 < methodt->rows)
7853                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7854         else
7855                 lastp = paramt->rows + 1;
7856
7857         for (i = param_index; i < lastp; ++i) {
7858                 guint32 paramseq;
7859
7860                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7861                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7862
7863                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7864                         continue;
7865
7866                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7867                 if (!crow) {
7868                         continue;
7869                 }
7870         
7871                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7872                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7873                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7874         }
7875
7876         return;
7877 }
7878
7879 MonoObject *
7880 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7881 {
7882         MonoError error;
7883         void *retval;
7884         MonoClass *klass;
7885         MonoObject *object;
7886         MonoType *basetype = type;
7887
7888         if (!blob)
7889                 return NULL;
7890         
7891         klass = mono_class_from_mono_type (type);
7892         if (klass->valuetype) {
7893                 object = mono_object_new_checked (domain, klass, &error);
7894                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7895                 retval = ((gchar *) object + sizeof (MonoObject));
7896                 if (klass->enumtype)
7897                         basetype = mono_class_enum_basetype (klass);
7898         } else {
7899                 retval = &object;
7900         }
7901                         
7902         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7903                 return object;
7904         else
7905                 return NULL;
7906 }
7907
7908 static int
7909 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7910         int found_sep;
7911         char *s;
7912         gboolean quoted = FALSE;
7913
7914         memset (assembly, 0, sizeof (MonoAssemblyName));
7915         assembly->culture = "";
7916         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7917
7918         if (*p == '"') {
7919                 quoted = TRUE;
7920                 p++;
7921         }
7922         assembly->name = p;
7923         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7924                 p++;
7925         if (quoted) {
7926                 if (*p != '"')
7927                         return 1;
7928                 *p = 0;
7929                 p++;
7930         }
7931         if (*p != ',')
7932                 return 1;
7933         *p = 0;
7934         /* Remove trailing whitespace */
7935         s = p - 1;
7936         while (*s && g_ascii_isspace (*s))
7937                 *s-- = 0;
7938         p ++;
7939         while (g_ascii_isspace (*p))
7940                 p++;
7941         while (*p) {
7942                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7943                         p += 8;
7944                         assembly->major = strtoul (p, &s, 10);
7945                         if (s == p || *s != '.')
7946                                 return 1;
7947                         p = ++s;
7948                         assembly->minor = strtoul (p, &s, 10);
7949                         if (s == p || *s != '.')
7950                                 return 1;
7951                         p = ++s;
7952                         assembly->build = strtoul (p, &s, 10);
7953                         if (s == p || *s != '.')
7954                                 return 1;
7955                         p = ++s;
7956                         assembly->revision = strtoul (p, &s, 10);
7957                         if (s == p)
7958                                 return 1;
7959                         p = s;
7960                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7961                         p += 8;
7962                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7963                                 assembly->culture = "";
7964                                 p += 7;
7965                         } else {
7966                                 assembly->culture = p;
7967                                 while (*p && *p != ',') {
7968                                         p++;
7969                                 }
7970                         }
7971                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7972                         p += 15;
7973                         if (strncmp (p, "null", 4) == 0) {
7974                                 p += 4;
7975                         } else {
7976                                 int len;
7977                                 gchar *start = p;
7978                                 while (*p && *p != ',') {
7979                                         p++;
7980                                 }
7981                                 len = (p - start + 1);
7982                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7983                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7984                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7985                         }
7986                 } else {
7987                         while (*p && *p != ',')
7988                                 p++;
7989                 }
7990                 found_sep = 0;
7991                 while (g_ascii_isspace (*p) || *p == ',') {
7992                         *p++ = 0;
7993                         found_sep = 1;
7994                         continue;
7995                 }
7996                 /* failed */
7997                 if (!found_sep)
7998                         return 1;
7999         }
8000
8001         return 0;
8002 }
8003
8004 /*
8005  * mono_reflection_parse_type:
8006  * @name: type name
8007  *
8008  * Parse a type name as accepted by the GetType () method and output the info
8009  * extracted in the info structure.
8010  * the name param will be mangled, so, make a copy before passing it to this function.
8011  * The fields in info will be valid until the memory pointed to by name is valid.
8012  *
8013  * See also mono_type_get_name () below.
8014  *
8015  * Returns: 0 on parse error.
8016  */
8017 static int
8018 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8019                              MonoTypeNameParse *info)
8020 {
8021         char *start, *p, *w, *last_point, *startn;
8022         int in_modifiers = 0;
8023         int isbyref = 0, rank = 0, isptr = 0;
8024
8025         start = p = w = name;
8026
8027         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8028         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8029         info->name = info->name_space = NULL;
8030         info->nested = NULL;
8031         info->modifiers = NULL;
8032         info->type_arguments = NULL;
8033
8034         /* last_point separates the namespace from the name */
8035         last_point = NULL;
8036         /* Skips spaces */
8037         while (*p == ' ') p++, start++, w++, name++;
8038
8039         while (*p) {
8040                 switch (*p) {
8041                 case '+':
8042                         *p = 0; /* NULL terminate the name */
8043                         startn = p + 1;
8044                         info->nested = g_list_append (info->nested, startn);
8045                         /* we have parsed the nesting namespace + name */
8046                         if (info->name)
8047                                 break;
8048                         if (last_point) {
8049                                 info->name_space = start;
8050                                 *last_point = 0;
8051                                 info->name = last_point + 1;
8052                         } else {
8053                                 info->name_space = (char *)"";
8054                                 info->name = start;
8055                         }
8056                         break;
8057                 case '.':
8058                         last_point = p;
8059                         break;
8060                 case '\\':
8061                         ++p;
8062                         break;
8063                 case '&':
8064                 case '*':
8065                 case '[':
8066                 case ',':
8067                 case ']':
8068                         in_modifiers = 1;
8069                         break;
8070                 default:
8071                         break;
8072                 }
8073                 if (in_modifiers)
8074                         break;
8075                 // *w++ = *p++;
8076                 p++;
8077         }
8078         
8079         if (!info->name) {
8080                 if (last_point) {
8081                         info->name_space = start;
8082                         *last_point = 0;
8083                         info->name = last_point + 1;
8084                 } else {
8085                         info->name_space = (char *)"";
8086                         info->name = start;
8087                 }
8088         }
8089         while (*p) {
8090                 switch (*p) {
8091                 case '&':
8092                         if (isbyref) /* only one level allowed by the spec */
8093                                 return 0;
8094                         isbyref = 1;
8095                         isptr = 0;
8096                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8097                         *p++ = 0;
8098                         break;
8099                 case '*':
8100                         if (isbyref) /* pointer to ref not okay */
8101                                 return 0;
8102                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8103                         isptr = 1;
8104                         *p++ = 0;
8105                         break;
8106                 case '[':
8107                         if (isbyref) /* array of ref and generic ref are not okay */
8108                                 return 0;
8109                         //Decide if it's an array of a generic argument list
8110                         *p++ = 0;
8111
8112                         if (!*p) //XXX test
8113                                 return 0;
8114                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8115                                 isptr = 0;
8116                                 rank = 1;
8117                                 while (*p) {
8118                                         if (*p == ']')
8119                                                 break;
8120                                         if (*p == ',')
8121                                                 rank++;
8122                                         else if (*p == '*') /* '*' means unknown lower bound */
8123                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8124                                         else
8125                                                 return 0;
8126                                         ++p;
8127                                 }
8128                                 if (*p++ != ']')
8129                                         return 0;
8130                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8131                         } else {
8132                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8133                                         return 0;
8134                                 isptr = 0;
8135                                 info->type_arguments = g_ptr_array_new ();
8136                                 while (*p) {
8137                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8138                                         gboolean fqname = FALSE;
8139
8140                                         g_ptr_array_add (info->type_arguments, subinfo);
8141
8142                                         while (*p == ' ') p++;
8143                                         if (*p == '[') {
8144                                                 p++;
8145                                                 fqname = TRUE;
8146                                         }
8147
8148                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8149                                                 return 0;
8150
8151                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8152                                         if (fqname && (*p != ']')) {
8153                                                 char *aname;
8154
8155                                                 if (*p != ',')
8156                                                         return 0;
8157                                                 *p++ = 0;
8158
8159                                                 aname = p;
8160                                                 while (*p && (*p != ']'))
8161                                                         p++;
8162
8163                                                 if (*p != ']')
8164                                                         return 0;
8165
8166                                                 *p++ = 0;
8167                                                 while (*aname) {
8168                                                         if (g_ascii_isspace (*aname)) {
8169                                                                 ++aname;
8170                                                                 continue;
8171                                                         }
8172                                                         break;
8173                                                 }
8174                                                 if (!*aname ||
8175                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8176                                                         return 0;
8177                                         } else if (fqname && (*p == ']')) {
8178                                                 *p++ = 0;
8179                                         }
8180                                         if (*p == ']') {
8181                                                 *p++ = 0;
8182                                                 break;
8183                                         } else if (!*p) {
8184                                                 return 0;
8185                                         }
8186                                         *p++ = 0;
8187                                 }
8188                         }
8189                         break;
8190                 case ']':
8191                         if (is_recursed)
8192                                 goto end;
8193                         return 0;
8194                 case ',':
8195                         if (is_recursed)
8196                                 goto end;
8197                         *p++ = 0;
8198                         while (*p) {
8199                                 if (g_ascii_isspace (*p)) {
8200                                         ++p;
8201                                         continue;
8202                                 }
8203                                 break;
8204                         }
8205                         if (!*p)
8206                                 return 0; /* missing assembly name */
8207                         if (!assembly_name_to_aname (&info->assembly, p))
8208                                 return 0;
8209                         break;
8210                 default:
8211                         return 0;
8212                 }
8213                 if (info->assembly.name)
8214                         break;
8215         }
8216         // *w = 0; /* terminate class name */
8217  end:
8218         if (!info->name || !*info->name)
8219                 return 0;
8220         if (endptr)
8221                 *endptr = p;
8222         /* add other consistency checks */
8223         return 1;
8224 }
8225
8226
8227 /**
8228  * mono_identifier_unescape_type_name_chars:
8229  * @identifier: the display name of a mono type
8230  *
8231  * Returns:
8232  *  The name in internal form, that is without escaping backslashes.
8233  *
8234  *  The string is modified in place!
8235  */
8236 char*
8237 mono_identifier_unescape_type_name_chars(char* identifier)
8238 {
8239         char *w, *r;
8240         if (!identifier)
8241                 return NULL;
8242         for (w = r = identifier; *r != 0; r++)
8243         {
8244                 char c = *r;
8245                 if (c == '\\') {
8246                         r++;
8247                         if (*r == 0)
8248                                 break;
8249                         c = *r;
8250                 }
8251                 *w = c;
8252                 w++;
8253         }
8254         if (w != r)
8255                 *w = 0;
8256         return identifier;
8257 }
8258
8259 void
8260 mono_identifier_unescape_info (MonoTypeNameParse* info);
8261
8262 static void
8263 unescape_each_type_argument(void* data, void* user_data)
8264 {
8265         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8266         mono_identifier_unescape_info (info);
8267 }
8268
8269 static void
8270 unescape_each_nested_name (void* data, void* user_data)
8271 {
8272         char* nested_name = (char*) data;
8273         mono_identifier_unescape_type_name_chars(nested_name);
8274 }
8275
8276 /**
8277  * mono_identifier_unescape_info:
8278  *
8279  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8280  *
8281  * Returns: nothing.
8282  *
8283  * Destructively updates the info by unescaping the identifiers that
8284  * comprise the type namespace, name, nested types (if any) and
8285  * generic type arguments (if any).
8286  *
8287  * The resulting info has the names in internal form.
8288  *
8289  */
8290 void
8291 mono_identifier_unescape_info (MonoTypeNameParse *info)
8292 {
8293         if (!info)
8294                 return;
8295         mono_identifier_unescape_type_name_chars(info->name_space);
8296         mono_identifier_unescape_type_name_chars(info->name);
8297         // but don't escape info->assembly
8298         if (info->type_arguments)
8299                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8300         if (info->nested)
8301                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8302 }
8303
8304 int
8305 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8306 {
8307         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8308         if (ok) {
8309                 mono_identifier_unescape_info (info);
8310         }
8311         return ok;
8312 }
8313
8314 static MonoType*
8315 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8316 {
8317         gboolean type_resolve = FALSE;
8318         MonoType *type;
8319         MonoImage *rootimage = image;
8320
8321         if (info->assembly.name) {
8322                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8323                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8324                         /* 
8325                          * This could happen in the AOT compiler case when the search hook is not
8326                          * installed.
8327                          */
8328                         assembly = image->assembly;
8329                 if (!assembly) {
8330                         /* then we must load the assembly ourselve - see #60439 */
8331                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8332                         if (!assembly)
8333                                 return NULL;
8334                 }
8335                 image = assembly->image;
8336         } else if (!image) {
8337                 image = mono_defaults.corlib;
8338         }
8339
8340         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8341         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8342                 image = mono_defaults.corlib;
8343                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8344         }
8345
8346         return type;
8347 }
8348
8349 /**
8350  * mono_reflection_get_type_internal:
8351  *
8352  * Returns: may return NULL on success, sets error on failure.
8353  */
8354 static MonoType*
8355 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8356 {
8357         MonoClass *klass;
8358         GList *mod;
8359         int modval;
8360         gboolean bounded = FALSE;
8361         
8362         mono_error_init (error);
8363         if (!image)
8364                 image = mono_defaults.corlib;
8365
8366         if (!rootimage)
8367                 rootimage = mono_defaults.corlib;
8368
8369         if (ignorecase)
8370                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8371         else
8372                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8373
8374         if (!klass)
8375                 return NULL;
8376
8377         for (mod = info->nested; mod; mod = mod->next) {
8378                 gpointer iter = NULL;
8379                 MonoClass *parent;
8380
8381                 parent = klass;
8382                 mono_class_init (parent);
8383
8384                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8385                         char *lastp;
8386                         char *nested_name, *nested_nspace;
8387                         gboolean match = TRUE;
8388
8389                         lastp = strrchr ((const char *)mod->data, '.');
8390                         if (lastp) {
8391                                 /* Nested classes can have namespaces */
8392                                 int nspace_len;
8393
8394                                 nested_name = g_strdup (lastp + 1);
8395                                 nspace_len = lastp - (char*)mod->data;
8396                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8397                                 memcpy (nested_nspace, mod->data, nspace_len);
8398                                 nested_nspace [nspace_len] = '\0';
8399
8400                         } else {
8401                                 nested_name = (char *)mod->data;
8402                                 nested_nspace = NULL;
8403                         }
8404
8405                         if (nested_nspace) {
8406                                 if (ignorecase) {
8407                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8408                                                 match = FALSE;
8409                                 } else {
8410                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8411                                                 match = FALSE;
8412                                 }
8413                         }
8414                         if (match) {
8415                                 if (ignorecase) {
8416                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8417                                                 match = FALSE;
8418                                 } else {
8419                                         if (strcmp (klass->name, nested_name) != 0)
8420                                                 match = FALSE;
8421                                 }
8422                         }
8423                         if (lastp) {
8424                                 g_free (nested_name);
8425                                 g_free (nested_nspace);
8426                         }
8427                         if (match)
8428                                 break;
8429                 }
8430
8431                 if (!klass)
8432                         break;
8433         }
8434         if (!klass)
8435                 return NULL;
8436
8437         if (info->type_arguments) {
8438                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8439                 MonoReflectionType *the_type;
8440                 MonoType *instance;
8441                 int i;
8442
8443                 for (i = 0; i < info->type_arguments->len; i++) {
8444                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8445
8446                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8447                         if (!type_args [i]) {
8448                                 g_free (type_args);
8449                                 return NULL;
8450                         }
8451                 }
8452
8453                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8454                 if (!the_type)
8455                         return NULL;
8456
8457                 instance = mono_reflection_bind_generic_parameters (
8458                         the_type, info->type_arguments->len, type_args);
8459
8460                 g_free (type_args);
8461                 if (!instance)
8462                         return NULL;
8463
8464                 klass = mono_class_from_mono_type (instance);
8465         }
8466
8467         for (mod = info->modifiers; mod; mod = mod->next) {
8468                 modval = GPOINTER_TO_UINT (mod->data);
8469                 if (!modval) { /* byref: must be last modifier */
8470                         return &klass->this_arg;
8471                 } else if (modval == -1) {
8472                         klass = mono_ptr_class_get (&klass->byval_arg);
8473                 } else if (modval == -2) {
8474                         bounded = TRUE;
8475                 } else { /* array rank */
8476                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8477                 }
8478         }
8479
8480         return &klass->byval_arg;
8481 }
8482
8483 /*
8484  * mono_reflection_get_type:
8485  * @image: a metadata context
8486  * @info: type description structure
8487  * @ignorecase: flag for case-insensitive string compares
8488  * @type_resolve: whenever type resolve was already tried
8489  *
8490  * Build a MonoType from the type description in @info.
8491  * 
8492  */
8493
8494 MonoType*
8495 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8496         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8497 }
8498
8499 static MonoType*
8500 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8501 {
8502         MonoReflectionAssemblyBuilder *abuilder;
8503         MonoType *type;
8504         int i;
8505
8506         mono_error_init (error);
8507         g_assert (assembly_is_dynamic (assembly));
8508         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8509         if (!abuilder)
8510                 return NULL;
8511
8512         /* Enumerate all modules */
8513
8514         type = NULL;
8515         if (abuilder->modules) {
8516                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8517                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8518                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8519                         if (type)
8520                                 break;
8521                         if (!mono_error_ok (error))
8522                                 return NULL;
8523                 }
8524         }
8525
8526         if (!type && abuilder->loaded_modules) {
8527                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8528                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8529                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8530                         if (type)
8531                                 break;
8532                         if (!mono_error_ok (error))
8533                                 return NULL;
8534                 }
8535         }
8536
8537         return type;
8538 }
8539         
8540 MonoType*
8541 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8542 {
8543         MonoError error;
8544         MonoType *type;
8545         MonoReflectionAssembly *assembly;
8546         GString *fullName;
8547         GList *mod;
8548
8549         if (image && image_is_dynamic (image))
8550                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8551         else {
8552                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8553         }
8554         if (!mono_error_ok (&error))
8555                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8556
8557         if (type)
8558                 return type;
8559         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8560                 return NULL;
8561
8562         if (type_resolve) {
8563                 if (*type_resolve) 
8564                         return NULL;
8565                 else
8566                         *type_resolve = TRUE;
8567         }
8568         
8569         /* Reconstruct the type name */
8570         fullName = g_string_new ("");
8571         if (info->name_space && (info->name_space [0] != '\0'))
8572                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8573         else
8574                 g_string_printf (fullName, "%s", info->name);
8575         for (mod = info->nested; mod; mod = mod->next)
8576                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8577
8578         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8579         mono_error_raise_exception (&error); /* FIXME don't raise here */
8580
8581         if (assembly) {
8582                 if (assembly_is_dynamic (assembly->assembly))
8583                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8584                                                                           info, ignorecase, &error);
8585                 else
8586                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8587                                                                   info, ignorecase, &error);
8588         }
8589         g_string_free (fullName, TRUE);
8590         if (!mono_error_ok (&error))
8591                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8592         return type;
8593 }
8594
8595 void
8596 mono_reflection_free_type_info (MonoTypeNameParse *info)
8597 {
8598         g_list_free (info->modifiers);
8599         g_list_free (info->nested);
8600
8601         if (info->type_arguments) {
8602                 int i;
8603
8604                 for (i = 0; i < info->type_arguments->len; i++) {
8605                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8606
8607                         mono_reflection_free_type_info (subinfo);
8608                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8609                         g_free (subinfo);
8610                 }
8611
8612                 g_ptr_array_free (info->type_arguments, TRUE);
8613         }
8614 }
8615
8616 /*
8617  * mono_reflection_type_from_name:
8618  * @name: type name.
8619  * @image: a metadata context (can be NULL).
8620  *
8621  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8622  * it defaults to get the type from @image or, if @image is NULL or loading
8623  * from it fails, uses corlib.
8624  * 
8625  */
8626 MonoType*
8627 mono_reflection_type_from_name (char *name, MonoImage *image)
8628 {
8629         MonoType *type = NULL;
8630         MonoTypeNameParse info;
8631         char *tmp;
8632
8633         /* Make a copy since parse_type modifies its argument */
8634         tmp = g_strdup (name);
8635         
8636         /*g_print ("requested type %s\n", str);*/
8637         if (mono_reflection_parse_type (tmp, &info)) {
8638                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8639         }
8640
8641         g_free (tmp);
8642         mono_reflection_free_type_info (&info);
8643         return type;
8644 }
8645
8646 /*
8647  * mono_reflection_get_token:
8648  *
8649  *   Return the metadata token of OBJ which should be an object
8650  * representing a metadata element.
8651  */
8652 guint32
8653 mono_reflection_get_token (MonoObject *obj)
8654 {
8655         MonoError error;
8656         MonoClass *klass;
8657         guint32 token = 0;
8658
8659         klass = obj->vtable->klass;
8660
8661         if (strcmp (klass->name, "MethodBuilder") == 0) {
8662                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8663
8664                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8665         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8666                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8667
8668                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8669         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8670                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8671
8672                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8673         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8674                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8675                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8676         } else if (strcmp (klass->name, "MonoType") == 0) {
8677                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8678                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8679                 MonoClass *mc = mono_class_from_mono_type (type);
8680                 if (!mono_class_init (mc))
8681                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8682
8683                 token = mc->type_token;
8684         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8685                    strcmp (klass->name, "MonoMethod") == 0 ||
8686                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8687                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8688                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8689                 if (m->method->is_inflated) {
8690                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8691                         return inflated->declaring->token;
8692                 } else {
8693                         token = m->method->token;
8694                 }
8695         } else if (strcmp (klass->name, "MonoField") == 0) {
8696                 MonoReflectionField *f = (MonoReflectionField*)obj;
8697
8698                 if (is_field_on_inst (f->field)) {
8699                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8700
8701                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8702                                 int field_index = f->field - dgclass->fields;
8703                                 MonoObject *obj;
8704
8705                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8706                                 obj = dgclass->field_objects [field_index];
8707                                 return mono_reflection_get_token (obj);
8708                         }
8709                 }
8710                 token = mono_class_get_field_token (f->field);
8711         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8712                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8713
8714                 token = mono_class_get_property_token (p->property);
8715         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8716                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8717
8718                 token = mono_class_get_event_token (p->event);
8719         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8720                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8721                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8722                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8723
8724                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8725         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8726                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8727
8728                 token = m->token;
8729         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8730                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8731         } else {
8732                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8733                 MonoException *ex = mono_get_exception_not_implemented (msg);
8734                 g_free (msg);
8735                 mono_raise_exception (ex);
8736         }
8737
8738         return token;
8739 }
8740
8741 static MonoClass*
8742 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8743 {
8744         char *n;
8745         MonoType *t;
8746         int slen = mono_metadata_decode_value (p, &p);
8747
8748         mono_error_init (error);
8749
8750         n = (char *)g_memdup (p, slen + 1);
8751         n [slen] = 0;
8752         t = mono_reflection_type_from_name (n, image);
8753         if (!t) {
8754                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8755                 /* We don't free n, it's consumed by mono_error */
8756                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8757                 return NULL;
8758         }
8759         g_free (n);
8760         p += slen;
8761         *end = p;
8762         return mono_class_from_mono_type (t);
8763 }
8764
8765 static void*
8766 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8767 {
8768         int slen, type = t->type;
8769         MonoClass *tklass = t->data.klass;
8770
8771         mono_error_init (error);
8772
8773 handle_enum:
8774         switch (type) {
8775         case MONO_TYPE_U1:
8776         case MONO_TYPE_I1:
8777         case MONO_TYPE_BOOLEAN: {
8778                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8779                 *bval = *p;
8780                 *end = p + 1;
8781                 return bval;
8782         }
8783         case MONO_TYPE_CHAR:
8784         case MONO_TYPE_U2:
8785         case MONO_TYPE_I2: {
8786                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8787                 *val = read16 (p);
8788                 *end = p + 2;
8789                 return val;
8790         }
8791 #if SIZEOF_VOID_P == 4
8792         case MONO_TYPE_U:
8793         case MONO_TYPE_I:
8794 #endif
8795         case MONO_TYPE_R4:
8796         case MONO_TYPE_U4:
8797         case MONO_TYPE_I4: {
8798                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8799                 *val = read32 (p);
8800                 *end = p + 4;
8801                 return val;
8802         }
8803 #if SIZEOF_VOID_P == 8
8804         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8805         case MONO_TYPE_I:
8806 #endif
8807         case MONO_TYPE_U8:
8808         case MONO_TYPE_I8: {
8809                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8810                 *val = read64 (p);
8811                 *end = p + 8;
8812                 return val;
8813         }
8814         case MONO_TYPE_R8: {
8815                 double *val = (double *)g_malloc (sizeof (double));
8816                 readr8 (p, val);
8817                 *end = p + 8;
8818                 return val;
8819         }
8820         case MONO_TYPE_VALUETYPE:
8821                 if (t->data.klass->enumtype) {
8822                         type = mono_class_enum_basetype (t->data.klass)->type;
8823                         goto handle_enum;
8824                 } else {
8825                         MonoClass *k =  t->data.klass;
8826                         
8827                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8828                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8829                                 *val = read64 (p);
8830                                 *end = p + 8;
8831                                 return val;
8832                         }
8833                 }
8834                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8835                 break;
8836                 
8837         case MONO_TYPE_STRING:
8838                 if (*p == (char)0xFF) {
8839                         *end = p + 1;
8840                         return NULL;
8841                 }
8842                 slen = mono_metadata_decode_value (p, &p);
8843                 *end = p + slen;
8844                 return mono_string_new_len (mono_domain_get (), p, slen);
8845         case MONO_TYPE_CLASS: {
8846                 MonoReflectionType *rt;
8847                 char *n;
8848                 MonoType *t;
8849                 if (*p == (char)0xFF) {
8850                         *end = p + 1;
8851                         return NULL;
8852                 }
8853 handle_type:
8854                 slen = mono_metadata_decode_value (p, &p);
8855                 n = (char *)g_memdup (p, slen + 1);
8856                 n [slen] = 0;
8857                 t = mono_reflection_type_from_name (n, image);
8858                 if (!t) {
8859                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8860                         /* We don't free n, it's consumed by mono_error */
8861                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8862                         return NULL;
8863                 }
8864                 g_free (n);
8865                 *end = p + slen;
8866
8867                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8868                 if (!mono_error_ok (error))
8869                         return NULL;
8870
8871                 return rt;
8872         }
8873         case MONO_TYPE_OBJECT: {
8874                 char subt = *p++;
8875                 MonoObject *obj;
8876                 MonoClass *subc = NULL;
8877                 void *val;
8878
8879                 if (subt == 0x50) {
8880                         goto handle_type;
8881                 } else if (subt == 0x0E) {
8882                         type = MONO_TYPE_STRING;
8883                         goto handle_enum;
8884                 } else if (subt == 0x1D) {
8885                         MonoType simple_type = {{0}};
8886                         int etype = *p;
8887                         p ++;
8888
8889                         type = MONO_TYPE_SZARRAY;
8890                         if (etype == 0x50) {
8891                                 tklass = mono_defaults.systemtype_class;
8892                         } else if (etype == 0x55) {
8893                                 tklass = load_cattr_enum_type (image, p, &p, error);
8894                                 if (!mono_error_ok (error))
8895                                         return NULL;
8896                         } else {
8897                                 if (etype == 0x51)
8898                                         /* See Partition II, Appendix B3 */
8899                                         etype = MONO_TYPE_OBJECT;
8900                                 simple_type.type = (MonoTypeEnum)etype;
8901                                 tklass = mono_class_from_mono_type (&simple_type);
8902                         }
8903                         goto handle_enum;
8904                 } else if (subt == 0x55) {
8905                         char *n;
8906                         MonoType *t;
8907                         slen = mono_metadata_decode_value (p, &p);
8908                         n = (char *)g_memdup (p, slen + 1);
8909                         n [slen] = 0;
8910                         t = mono_reflection_type_from_name (n, image);
8911                         if (!t) {
8912                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8913                                 /* We don't free n, it's consumed by mono_error */
8914                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8915                                 return NULL;
8916                         }
8917                         g_free (n);
8918                         p += slen;
8919                         subc = mono_class_from_mono_type (t);
8920                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8921                         MonoType simple_type = {{0}};
8922                         simple_type.type = (MonoTypeEnum)subt;
8923                         subc = mono_class_from_mono_type (&simple_type);
8924                 } else {
8925                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8926                 }
8927                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8928                 obj = NULL;
8929                 if (mono_error_ok (error)) {
8930                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
8931                         g_assert (!subc->has_references);
8932                         if (mono_error_ok (error))
8933                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8934                 }
8935
8936                 g_free (val);
8937                 return obj;
8938         }
8939         case MONO_TYPE_SZARRAY: {
8940                 MonoArray *arr;
8941                 guint32 i, alen, basetype;
8942                 alen = read32 (p);
8943                 p += 4;
8944                 if (alen == 0xffffffff) {
8945                         *end = p;
8946                         return NULL;
8947                 }
8948                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8949                 basetype = tklass->byval_arg.type;
8950                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8951                         basetype = mono_class_enum_basetype (tklass)->type;
8952                 switch (basetype)
8953                 {
8954                         case MONO_TYPE_U1:
8955                         case MONO_TYPE_I1:
8956                         case MONO_TYPE_BOOLEAN:
8957                                 for (i = 0; i < alen; i++) {
8958                                         MonoBoolean val = *p++;
8959                                         mono_array_set (arr, MonoBoolean, i, val);
8960                                 }
8961                                 break;
8962                         case MONO_TYPE_CHAR:
8963                         case MONO_TYPE_U2:
8964                         case MONO_TYPE_I2:
8965                                 for (i = 0; i < alen; i++) {
8966                                         guint16 val = read16 (p);
8967                                         mono_array_set (arr, guint16, i, val);
8968                                         p += 2;
8969                                 }
8970                                 break;
8971                         case MONO_TYPE_R4:
8972                         case MONO_TYPE_U4:
8973                         case MONO_TYPE_I4:
8974                                 for (i = 0; i < alen; i++) {
8975                                         guint32 val = read32 (p);
8976                                         mono_array_set (arr, guint32, i, val);
8977                                         p += 4;
8978                                 }
8979                                 break;
8980                         case MONO_TYPE_R8:
8981                                 for (i = 0; i < alen; i++) {
8982                                         double val;
8983                                         readr8 (p, &val);
8984                                         mono_array_set (arr, double, i, val);
8985                                         p += 8;
8986                                 }
8987                                 break;
8988                         case MONO_TYPE_U8:
8989                         case MONO_TYPE_I8:
8990                                 for (i = 0; i < alen; i++) {
8991                                         guint64 val = read64 (p);
8992                                         mono_array_set (arr, guint64, i, val);
8993                                         p += 8;
8994                                 }
8995                                 break;
8996                         case MONO_TYPE_CLASS:
8997                         case MONO_TYPE_OBJECT:
8998                         case MONO_TYPE_STRING:
8999                         case MONO_TYPE_SZARRAY:
9000                                 for (i = 0; i < alen; i++) {
9001                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9002                                         if (!mono_error_ok (error))
9003                                                 return NULL;
9004                                         mono_array_setref (arr, i, item);
9005                                 }
9006                                 break;
9007                         default:
9008                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9009                 }
9010                 *end=p;
9011                 return arr;
9012         }
9013         default:
9014                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9015         }
9016         return NULL;
9017 }
9018
9019 static MonoObject*
9020 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9021 {
9022         static MonoMethod *ctor;
9023         MonoObject *retval;
9024         void *params [2], *unboxed;
9025
9026         mono_error_init (error);
9027
9028         if (!ctor)
9029                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9030         
9031         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9032         return_val_if_nok (error, NULL);
9033
9034         params [1] = val;
9035         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9036         return_val_if_nok (error, NULL);
9037         unboxed = mono_object_unbox (retval);
9038
9039         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9040         return_val_if_nok (error, NULL);
9041
9042         return retval;
9043 }
9044
9045 static MonoObject*
9046 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9047 {
9048         static MonoMethod *ctor;
9049         MonoObject *retval;
9050         void *unboxed, *params [2];
9051
9052         mono_error_init (error);
9053
9054         if (!ctor)
9055                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9056
9057         params [0] = minfo;
9058         params [1] = typedarg;
9059         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9060         return_val_if_nok (error, NULL);
9061
9062         unboxed = mono_object_unbox (retval);
9063
9064         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9065         return_val_if_nok (error, NULL);
9066
9067         return retval;
9068 }
9069
9070 static gboolean
9071 type_is_reference (MonoType *type)
9072 {
9073         switch (type->type) {
9074         case MONO_TYPE_BOOLEAN:
9075         case MONO_TYPE_CHAR:
9076         case MONO_TYPE_U:
9077         case MONO_TYPE_I:
9078         case MONO_TYPE_U1:
9079         case MONO_TYPE_I1:
9080         case MONO_TYPE_U2:
9081         case MONO_TYPE_I2:
9082         case MONO_TYPE_U4:
9083         case MONO_TYPE_I4:
9084         case MONO_TYPE_U8:
9085         case MONO_TYPE_I8:
9086         case MONO_TYPE_R8:
9087         case MONO_TYPE_R4:
9088         case MONO_TYPE_VALUETYPE:
9089                 return FALSE;
9090         default:
9091                 return TRUE;
9092         }
9093 }
9094
9095 static void
9096 free_param_data (MonoMethodSignature *sig, void **params) {
9097         int i;
9098         for (i = 0; i < sig->param_count; ++i) {
9099                 if (!type_is_reference (sig->params [i]))
9100                         g_free (params [i]);
9101         }
9102 }
9103
9104 /*
9105  * Find the field index in the metadata FieldDef table.
9106  */
9107 static guint32
9108 find_field_index (MonoClass *klass, MonoClassField *field) {
9109         int i;
9110
9111         for (i = 0; i < klass->field.count; ++i) {
9112                 if (field == &klass->fields [i])
9113                         return klass->field.first + 1 + i;
9114         }
9115         return 0;
9116 }
9117
9118 /*
9119  * Find the property index in the metadata Property table.
9120  */
9121 static guint32
9122 find_property_index (MonoClass *klass, MonoProperty *property) {
9123         int i;
9124
9125         for (i = 0; i < klass->ext->property.count; ++i) {
9126                 if (property == &klass->ext->properties [i])
9127                         return klass->ext->property.first + 1 + i;
9128         }
9129         return 0;
9130 }
9131
9132 /*
9133  * Find the event index in the metadata Event table.
9134  */
9135 static guint32
9136 find_event_index (MonoClass *klass, MonoEvent *event) {
9137         int i;
9138
9139         for (i = 0; i < klass->ext->event.count; ++i) {
9140                 if (event == &klass->ext->events [i])
9141                         return klass->ext->event.first + 1 + i;
9142         }
9143         return 0;
9144 }
9145
9146 static MonoObject*
9147 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9148 {
9149         const char *p = (const char*)data;
9150         const char *named;
9151         guint32 i, j, num_named;
9152         MonoObject *attr;
9153         void *params_buf [32];
9154         void **params = NULL;
9155         MonoMethodSignature *sig;
9156         MonoObject *exc = NULL;
9157
9158         mono_error_init (error);
9159
9160         mono_class_init (method->klass);
9161
9162         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9163                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9164                 return NULL;
9165         }
9166
9167         if (len == 0) {
9168                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9169                 if (!mono_error_ok (error)) return NULL;
9170
9171                 mono_runtime_invoke_checked (method, attr, NULL, error);
9172                 if (!mono_error_ok (error))
9173                         return NULL;
9174
9175                 return attr;
9176         }
9177
9178         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9179                 return NULL;
9180
9181         /*g_print ("got attr %s\n", method->klass->name);*/
9182
9183         sig = mono_method_signature (method);
9184         if (sig->param_count < 32) {
9185                 params = params_buf;
9186                 memset (params, 0, sizeof (void*) * sig->param_count);
9187         } else {
9188                 /* Allocate using GC so it gets GC tracking */
9189                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9190         }
9191
9192         /* skip prolog */
9193         p += 2;
9194         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9195                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9196                 if (!mono_error_ok (error))
9197                         goto fail;
9198         }
9199
9200         named = p;
9201         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9202         if (!mono_error_ok (error)) goto fail;
9203
9204         mono_runtime_try_invoke (method, attr, params, &exc, error);
9205         if (!mono_error_ok (error))
9206                 goto fail;
9207         if (exc)
9208                 goto fail;
9209
9210         num_named = read16 (named);
9211         named += 2;
9212         for (j = 0; j < num_named; j++) {
9213                 gint name_len;
9214                 char *name, named_type, data_type;
9215                 named_type = *named++;
9216                 data_type = *named++; /* type of data */
9217                 if (data_type == MONO_TYPE_SZARRAY)
9218                         data_type = *named++;
9219                 if (data_type == MONO_TYPE_ENUM) {
9220                         gint type_len;
9221                         char *type_name;
9222                         type_len = mono_metadata_decode_blob_size (named, &named);
9223                         type_name = (char *)g_malloc (type_len + 1);
9224                         memcpy (type_name, named, type_len);
9225                         type_name [type_len] = 0;
9226                         named += type_len;
9227                         /* FIXME: lookup the type and check type consistency */
9228                         g_free (type_name);
9229                 }
9230                 name_len = mono_metadata_decode_blob_size (named, &named);
9231                 name = (char *)g_malloc (name_len + 1);
9232                 memcpy (name, named, name_len);
9233                 name [name_len] = 0;
9234                 named += name_len;
9235                 if (named_type == 0x53) {
9236                         MonoClassField *field;
9237                         void *val;
9238
9239                         /* how this fail is a blackbox */
9240                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9241                         if (!field) {
9242                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9243                                 g_free (name);
9244                                 goto fail;
9245                         }
9246
9247                         val = load_cattr_value (image, field->type, named, &named, error);
9248                         if (!mono_error_ok (error)) {
9249                                 g_free (name);
9250                                 if (!type_is_reference (field->type))
9251                                         g_free (val);
9252                                 goto fail;
9253                         }
9254
9255                         mono_field_set_value (attr, field, val);
9256                         if (!type_is_reference (field->type))
9257                                 g_free (val);
9258                 } else if (named_type == 0x54) {
9259                         MonoProperty *prop;
9260                         void *pparams [1];
9261                         MonoType *prop_type;
9262
9263                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9264
9265                         if (!prop) {
9266                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9267                                 g_free (name);
9268                                 goto fail;
9269                         }
9270
9271                         if (!prop->set) {
9272                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9273                                 g_free (name);
9274                                 goto fail;
9275                         }
9276
9277                         /* can we have more that 1 arg in a custom attr named property? */
9278                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9279                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9280
9281                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9282                         if (!mono_error_ok (error)) {
9283                                 g_free (name);
9284                                 if (!type_is_reference (prop_type))
9285                                         g_free (pparams [0]);
9286                                 goto fail;
9287                         }
9288
9289
9290                         mono_property_set_value (prop, attr, pparams, NULL);
9291                         if (!type_is_reference (prop_type))
9292                                 g_free (pparams [0]);
9293                 }
9294                 g_free (name);
9295         }
9296
9297         free_param_data (method->signature, params);
9298         if (params != params_buf)
9299                 mono_gc_free_fixed (params);
9300
9301         return attr;
9302
9303 fail:
9304         free_param_data (method->signature, params);
9305         if (params != params_buf)
9306                 mono_gc_free_fixed (params);
9307         if (exc)
9308                 mono_raise_exception ((MonoException*)exc);
9309         return NULL;
9310 }
9311         
9312 /*
9313  * mono_reflection_create_custom_attr_data_args:
9314  *
9315  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9316  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9317  * NAMED_ARG_INFO will contain information about the named arguments.
9318  */
9319 void
9320 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)
9321 {
9322         MonoArray *typedargs, *namedargs;
9323         MonoClass *attrklass;
9324         MonoDomain *domain;
9325         const char *p = (const char*)data;
9326         const char *named;
9327         guint32 i, j, num_named;
9328         CattrNamedArg *arginfo = NULL;
9329
9330         *typed_args = NULL;
9331         *named_args = NULL;
9332         *named_arg_info = NULL;
9333
9334         mono_error_init (error);
9335
9336         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9337                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9338                 return;
9339         }
9340
9341         mono_class_init (method->klass);
9342         
9343         domain = mono_domain_get ();
9344
9345         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9346                 return;
9347
9348         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9349         
9350         /* skip prolog */
9351         p += 2;
9352         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9353                 MonoObject *obj;
9354                 void *val;
9355
9356                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9357                 if (!mono_error_ok (error)) {
9358                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9359                                 g_free (val);
9360                         return;
9361                 }
9362
9363                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9364                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9365                 mono_array_setref (typedargs, i, obj);
9366
9367                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9368                         g_free (val);
9369         }
9370
9371         named = p;
9372         num_named = read16 (named);
9373         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9374         named += 2;
9375         attrklass = method->klass;
9376
9377         arginfo = g_new0 (CattrNamedArg, num_named);
9378         *named_arg_info = arginfo;
9379
9380         for (j = 0; j < num_named; j++) {
9381                 gint name_len;
9382                 char *name, named_type, data_type;
9383                 named_type = *named++;
9384                 data_type = *named++; /* type of data */
9385                 if (data_type == MONO_TYPE_SZARRAY)
9386                         data_type = *named++;
9387                 if (data_type == MONO_TYPE_ENUM) {
9388                         gint type_len;
9389                         char *type_name;
9390                         type_len = mono_metadata_decode_blob_size (named, &named);
9391                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9392                                 goto fail;
9393
9394                         type_name = (char *)g_malloc (type_len + 1);
9395                         memcpy (type_name, named, type_len);
9396                         type_name [type_len] = 0;
9397                         named += type_len;
9398                         /* FIXME: lookup the type and check type consistency */
9399                         g_free (type_name);
9400                 }
9401                 name_len = mono_metadata_decode_blob_size (named, &named);
9402                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9403                         goto fail;
9404                 name = (char *)g_malloc (name_len + 1);
9405                 memcpy (name, named, name_len);
9406                 name [name_len] = 0;
9407                 named += name_len;
9408                 if (named_type == 0x53) {
9409                         MonoObject *obj;
9410                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9411                         void *val;
9412
9413                         if (!field) {
9414                                 g_free (name);
9415                                 goto fail;
9416                         }
9417
9418                         arginfo [j].type = field->type;
9419                         arginfo [j].field = field;
9420
9421                         val = load_cattr_value (image, field->type, named, &named, error);
9422                         if (!mono_error_ok (error)) {
9423                                 if (!type_is_reference (field->type))
9424                                         g_free (val);
9425                                 g_free (name);
9426                                 return;
9427                         }
9428
9429                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9430                         mono_array_setref (namedargs, j, obj);
9431                         if (!type_is_reference (field->type))
9432                                 g_free (val);
9433                 } else if (named_type == 0x54) {
9434                         MonoObject *obj;
9435                         MonoType *prop_type;
9436                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9437                         void *val;
9438
9439                         if (!prop || !prop->set) {
9440                                 g_free (name);
9441                                 goto fail;
9442                         }
9443
9444                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9445                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9446
9447                         arginfo [j].type = prop_type;
9448                         arginfo [j].prop = prop;
9449
9450                         val = load_cattr_value (image, prop_type, named, &named, error);
9451                         if (!mono_error_ok (error)) {
9452                                 if (!type_is_reference (prop_type))
9453                                         g_free (val);
9454                                 g_free (name);
9455                                 return;
9456                         }
9457
9458                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9459                         mono_array_setref (namedargs, j, obj);
9460                         if (!type_is_reference (prop_type))
9461                                 g_free (val);
9462                 }
9463                 g_free (name);
9464         }
9465
9466         *typed_args = typedargs;
9467         *named_args = namedargs;
9468         return;
9469 fail:
9470         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9471         g_free (arginfo);
9472         *named_arg_info = NULL;
9473 }
9474
9475 void
9476 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9477 {
9478         MonoDomain *domain;
9479         MonoArray *typedargs, *namedargs;
9480         MonoImage *image;
9481         MonoMethod *method;
9482         CattrNamedArg *arginfo = NULL;
9483         MonoError error;
9484         int i;
9485
9486         mono_error_init (&error);
9487
9488         *ctor_args = NULL;
9489         *named_args = NULL;
9490
9491         if (len == 0)
9492                 return;
9493
9494         image = assembly->assembly->image;
9495         method = ref_method->method;
9496         domain = mono_object_domain (ref_method);
9497
9498         if (!mono_class_init (method->klass))
9499                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9500
9501         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9502         if (!mono_error_ok (&error))
9503                 goto leave;
9504
9505         if (mono_loader_get_last_error ()) {
9506                 mono_error_set_from_loader_error (&error);
9507                 goto leave;
9508         }
9509
9510         if (!typedargs || !namedargs)
9511                 goto leave;
9512
9513         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9514                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9515                 MonoObject *typedarg;
9516
9517                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9518                 if (!is_ok (&error))
9519                         goto leave;
9520                 mono_array_setref (typedargs, i, typedarg);
9521         }
9522
9523         for (i = 0; i < mono_array_length (namedargs); ++i) {
9524                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9525                 MonoObject *typedarg, *namedarg, *minfo;
9526
9527                 if (arginfo [i].prop) {
9528                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9529                         if (!minfo)
9530                                 goto leave;
9531                 } else {
9532                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9533                         if (!mono_error_ok (&error))
9534                                 goto leave;
9535                 }
9536
9537                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9538                 if (!is_ok (&error))
9539                         goto leave;
9540                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9541                 if (!is_ok (&error))
9542                         goto leave;
9543
9544                 mono_array_setref (namedargs, i, namedarg);
9545         }
9546
9547         *ctor_args = typedargs;
9548         *named_args = namedargs;
9549 leave:
9550         g_free (arginfo);
9551         mono_error_raise_exception (&error);
9552
9553 }
9554
9555 static MonoObject*
9556 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9557 {
9558         static MonoMethod *ctor;
9559
9560         MonoDomain *domain;
9561         MonoObject *attr;
9562         void *params [4];
9563
9564         mono_error_init (error);
9565
9566         g_assert (image->assembly);
9567
9568         if (!ctor)
9569                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9570
9571         domain = mono_domain_get ();
9572         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9573         return_val_if_nok (error, NULL);
9574         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9575         return_val_if_nok (error, NULL);
9576         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9577         return_val_if_nok (error, NULL);
9578         params [2] = (gpointer)&cattr->data;
9579         params [3] = &cattr->data_size;
9580
9581         mono_runtime_invoke_checked (ctor, attr, params, error);
9582         return_val_if_nok (error, NULL);
9583         return attr;
9584 }
9585
9586 static MonoArray*
9587 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9588 {
9589         MonoArray *result;
9590         MonoObject *attr;
9591         int i, n;
9592
9593         mono_error_init (error);
9594
9595         n = 0;
9596         for (i = 0; i < cinfo->num_attrs; ++i) {
9597                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9598                         n ++;
9599         }
9600
9601         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9602         n = 0;
9603         for (i = 0; i < cinfo->num_attrs; ++i) {
9604                 if (!cinfo->attrs [i].ctor) {
9605                         /* The cattr type is not finished yet */
9606                         /* We should include the type name but cinfo doesn't contain it */
9607                         mono_error_set_type_load_name (error, NULL, NULL, "");
9608                         return NULL;
9609                 }
9610                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9611                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9612                         if (!mono_error_ok (error))
9613                                 return result;
9614                         mono_array_setref (result, n, attr);
9615                         n ++;
9616                 }
9617         }
9618         return result;
9619 }
9620
9621 MonoArray*
9622 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9623 {
9624         MonoError error;
9625         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9626         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9627
9628         return result;
9629 }
9630
9631 static MonoArray*
9632 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9633 {
9634         MonoArray *result;
9635         MonoObject *attr;
9636         int i;
9637         
9638         mono_error_init (error);
9639         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9640         for (i = 0; i < cinfo->num_attrs; ++i) {
9641                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9642                 return_val_if_nok (error, NULL);
9643                 mono_array_setref (result, i, attr);
9644         }
9645         return result;
9646 }
9647
9648 /**
9649  * mono_custom_attrs_from_index:
9650  *
9651  * Returns: NULL if no attributes are found or if a loading error occurs.
9652  */
9653 MonoCustomAttrInfo*
9654 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9655 {
9656         MonoError error;
9657         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9658         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9659         return result;
9660 }
9661 /**
9662  * mono_custom_attrs_from_index_checked:
9663  *
9664  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9665  */
9666 MonoCustomAttrInfo*
9667 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9668 {
9669         guint32 mtoken, i, len;
9670         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9671         MonoTableInfo *ca;
9672         MonoCustomAttrInfo *ainfo;
9673         GList *tmp, *list = NULL;
9674         const char *data;
9675         MonoCustomAttrEntry* attr;
9676
9677         mono_error_init (error);
9678
9679         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9680
9681         i = mono_metadata_custom_attrs_from_index (image, idx);
9682         if (!i)
9683                 return NULL;
9684         i --;
9685         while (i < ca->rows) {
9686                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9687                         break;
9688                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9689                 ++i;
9690         }
9691         len = g_list_length (list);
9692         if (!len)
9693                 return NULL;
9694         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9695         ainfo->num_attrs = len;
9696         ainfo->image = image;
9697         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9698                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9699                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9700                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9701                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9702                         mtoken |= MONO_TOKEN_METHOD_DEF;
9703                         break;
9704                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9705                         mtoken |= MONO_TOKEN_MEMBER_REF;
9706                         break;
9707                 default:
9708                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9709                         break;
9710                 }
9711                 attr = &ainfo->attrs [i - 1];
9712                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9713                 if (!attr->ctor) {
9714                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9715                         g_list_free (list);
9716                         g_free (ainfo);
9717                         return NULL;
9718                 }
9719
9720                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9721                         /*FIXME raising an exception here doesn't make any sense*/
9722                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9723                         g_list_free (list);
9724                         g_free (ainfo);
9725                         return NULL;
9726                 }
9727                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9728                 attr->data_size = mono_metadata_decode_value (data, &data);
9729                 attr->data = (guchar*)data;
9730         }
9731         g_list_free (list);
9732
9733         return ainfo;
9734 }
9735
9736 MonoCustomAttrInfo*
9737 mono_custom_attrs_from_method (MonoMethod *method)
9738 {
9739         MonoError error;
9740         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9741         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9742         return result;
9743 }
9744
9745 MonoCustomAttrInfo*
9746 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9747 {
9748         guint32 idx;
9749
9750         mono_error_init (error);
9751
9752         /*
9753          * An instantiated method has the same cattrs as the generic method definition.
9754          *
9755          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9756          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9757          */
9758         if (method->is_inflated)
9759                 method = ((MonoMethodInflated *) method)->declaring;
9760         
9761         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9762                 return lookup_custom_attr (method->klass->image, method);
9763
9764         if (!method->token)
9765                 /* Synthetic methods */
9766                 return NULL;
9767
9768         idx = mono_method_get_index (method);
9769         idx <<= MONO_CUSTOM_ATTR_BITS;
9770         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9771         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9772 }
9773
9774 MonoCustomAttrInfo*
9775 mono_custom_attrs_from_class (MonoClass *klass)
9776 {
9777         MonoError error;
9778         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9779         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9780         return result;
9781 }
9782
9783 MonoCustomAttrInfo*
9784 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9785 {
9786         guint32 idx;
9787
9788         mono_error_init (error);
9789
9790         if (klass->generic_class)
9791                 klass = klass->generic_class->container_class;
9792
9793         if (image_is_dynamic (klass->image))
9794                 return lookup_custom_attr (klass->image, klass);
9795
9796         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9797                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9798                 idx <<= MONO_CUSTOM_ATTR_BITS;
9799                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9800         } else {
9801                 idx = mono_metadata_token_index (klass->type_token);
9802                 idx <<= MONO_CUSTOM_ATTR_BITS;
9803                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9804         }
9805         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9806 }
9807
9808 MonoCustomAttrInfo*
9809 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9810 {
9811         MonoError error;
9812         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9813         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9814         return result;
9815 }
9816
9817 MonoCustomAttrInfo*
9818 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9819 {
9820         guint32 idx;
9821         
9822         mono_error_init (error);
9823
9824         if (image_is_dynamic (assembly->image))
9825                 return lookup_custom_attr (assembly->image, assembly);
9826         idx = 1; /* there is only one assembly */
9827         idx <<= MONO_CUSTOM_ATTR_BITS;
9828         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9829         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9830 }
9831
9832 static MonoCustomAttrInfo*
9833 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9834 {
9835         guint32 idx;
9836         
9837         if (image_is_dynamic (image))
9838                 return lookup_custom_attr (image, image);
9839         idx = 1; /* there is only one module */
9840         idx <<= MONO_CUSTOM_ATTR_BITS;
9841         idx |= MONO_CUSTOM_ATTR_MODULE;
9842         return mono_custom_attrs_from_index_checked (image, idx, error);
9843 }
9844
9845 MonoCustomAttrInfo*
9846 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9847 {
9848         MonoError error;
9849         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9850         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9851         return result;
9852 }
9853
9854 MonoCustomAttrInfo*
9855 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9856 {
9857         guint32 idx;
9858         
9859         if (image_is_dynamic (klass->image)) {
9860                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9861                 return lookup_custom_attr (klass->image, property);
9862         }
9863         idx = find_property_index (klass, property);
9864         idx <<= MONO_CUSTOM_ATTR_BITS;
9865         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9866         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9867 }
9868
9869 MonoCustomAttrInfo*
9870 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9871 {
9872         MonoError error;
9873         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9874         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9875         return result;
9876 }
9877
9878 MonoCustomAttrInfo*
9879 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9880 {
9881         guint32 idx;
9882         
9883         if (image_is_dynamic (klass->image)) {
9884                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9885                 return lookup_custom_attr (klass->image, event);
9886         }
9887         idx = find_event_index (klass, event);
9888         idx <<= MONO_CUSTOM_ATTR_BITS;
9889         idx |= MONO_CUSTOM_ATTR_EVENT;
9890         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9891 }
9892
9893 MonoCustomAttrInfo*
9894 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9895 {
9896         MonoError error;
9897         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9898         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9899         return result;
9900 }
9901
9902 MonoCustomAttrInfo*
9903 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9904 {
9905         guint32 idx;
9906         mono_error_init (error);
9907
9908         if (image_is_dynamic (klass->image)) {
9909                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9910                 return lookup_custom_attr (klass->image, field);
9911         }
9912         idx = find_field_index (klass, field);
9913         idx <<= MONO_CUSTOM_ATTR_BITS;
9914         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9915         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9916 }
9917
9918 /**
9919  * mono_custom_attrs_from_param:
9920  * @method: handle to the method that we want to retrieve custom parameter information from
9921  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9922  *
9923  * The result must be released with mono_custom_attrs_free().
9924  *
9925  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9926  */
9927 MonoCustomAttrInfo*
9928 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9929 {
9930         MonoError error;
9931         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9932         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9933         return result;
9934 }
9935
9936 /**
9937  * mono_custom_attrs_from_param_checked:
9938  * @method: handle to the method that we want to retrieve custom parameter information from
9939  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9940  * @error: set on error
9941  *
9942  * The result must be released with mono_custom_attrs_free().
9943  *
9944  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
9945  */
9946 MonoCustomAttrInfo*
9947 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9948 {
9949         MonoTableInfo *ca;
9950         guint32 i, idx, method_index;
9951         guint32 param_list, param_last, param_pos, found;
9952         MonoImage *image;
9953         MonoReflectionMethodAux *aux;
9954
9955         mono_error_init (error);
9956
9957         /*
9958          * An instantiated method has the same cattrs as the generic method definition.
9959          *
9960          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9961          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9962          */
9963         if (method->is_inflated)
9964                 method = ((MonoMethodInflated *) method)->declaring;
9965
9966         if (image_is_dynamic (method->klass->image)) {
9967                 MonoCustomAttrInfo *res, *ainfo;
9968                 int size;
9969
9970                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9971                 if (!aux || !aux->param_cattr)
9972                         return NULL;
9973
9974                 /* Need to copy since it will be freed later */
9975                 ainfo = aux->param_cattr [param];
9976                 if (!ainfo)
9977                         return NULL;
9978                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9979                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9980                 memcpy (res, ainfo, size);
9981                 return res;
9982         }
9983
9984         image = method->klass->image;
9985         method_index = mono_method_get_index (method);
9986         if (!method_index)
9987                 return NULL;
9988         ca = &image->tables [MONO_TABLE_METHOD];
9989
9990         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9991         if (method_index == ca->rows) {
9992                 ca = &image->tables [MONO_TABLE_PARAM];
9993                 param_last = ca->rows + 1;
9994         } else {
9995                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9996                 ca = &image->tables [MONO_TABLE_PARAM];
9997         }
9998         found = FALSE;
9999         for (i = param_list; i < param_last; ++i) {
10000                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10001                 if (param_pos == param) {
10002                         found = TRUE;
10003                         break;
10004                 }
10005         }
10006         if (!found)
10007                 return NULL;
10008         idx = i;
10009         idx <<= MONO_CUSTOM_ATTR_BITS;
10010         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10011         return mono_custom_attrs_from_index_checked (image, idx, error);
10012 }
10013
10014 gboolean
10015 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10016 {
10017         int i;
10018         MonoClass *klass;
10019         for (i = 0; i < ainfo->num_attrs; ++i) {
10020                 klass = ainfo->attrs [i].ctor->klass;
10021                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10022                         return TRUE;
10023         }
10024         return FALSE;
10025 }
10026
10027 MonoObject*
10028 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10029 {
10030         MonoError error;
10031         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10032         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10033         return res;
10034 }
10035
10036 MonoObject*
10037 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10038 {
10039         int i, attr_index;
10040         MonoClass *klass;
10041         MonoArray *attrs;
10042
10043         mono_error_init (error);
10044
10045         attr_index = -1;
10046         for (i = 0; i < ainfo->num_attrs; ++i) {
10047                 klass = ainfo->attrs [i].ctor->klass;
10048                 if (mono_class_has_parent (klass, attr_klass)) {
10049                         attr_index = i;
10050                         break;
10051                 }
10052         }
10053         if (attr_index == -1)
10054                 return NULL;
10055
10056         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10057         if (!mono_error_ok (error))
10058                 return NULL;
10059         return mono_array_get (attrs, MonoObject*, attr_index);
10060 }
10061
10062 /*
10063  * mono_reflection_get_custom_attrs_info:
10064  * @obj: a reflection object handle
10065  *
10066  * Return the custom attribute info for attributes defined for the
10067  * reflection handle @obj. The objects.
10068  *
10069  * FIXME this function leaks like a sieve for SRE objects.
10070  */
10071 MonoCustomAttrInfo*
10072 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10073 {
10074         MonoError error;
10075         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10076         mono_error_assert_ok (&error);
10077         return result;
10078 }
10079
10080 /**
10081  * mono_reflection_get_custom_attrs_info_checked:
10082  * @obj: a reflection object handle
10083  * @error: set on error
10084  *
10085  * Return the custom attribute info for attributes defined for the
10086  * reflection handle @obj. The objects.
10087  *
10088  * On failure returns NULL and sets @error.
10089  *
10090  * FIXME this function leaks like a sieve for SRE objects.
10091  */
10092 MonoCustomAttrInfo*
10093 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10094 {
10095         MonoClass *klass;
10096         MonoCustomAttrInfo *cinfo = NULL;
10097         
10098         mono_error_init (error);
10099
10100         klass = obj->vtable->klass;
10101         if (klass == mono_defaults.monotype_class) {
10102                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10103                 return_val_if_nok (error, NULL);
10104                 klass = mono_class_from_mono_type (type);
10105                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10106                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10107                 return_val_if_nok (error, NULL);
10108         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10109                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10110                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10111                 return_val_if_nok (error, NULL);
10112         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10113                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10114                 cinfo = mono_custom_attrs_from_module (module->image, error);
10115                 return_val_if_nok (error, NULL);
10116         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10117                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10118                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10119                 return_val_if_nok (error, NULL);
10120         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10121                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10122                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10123                 return_val_if_nok (error, NULL);
10124         } else if (strcmp ("MonoField", klass->name) == 0) {
10125                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10126                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10127                 return_val_if_nok (error, NULL);
10128         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10129                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10130                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10131                 return_val_if_nok (error, NULL);
10132         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10133                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10134                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10135                 return_val_if_nok (error, NULL);
10136         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10137                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10138                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10139                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10140                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10141                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10142                         return_val_if_nok (error, NULL);
10143                 } else if (is_sr_mono_property (member_class)) {
10144                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10145                         MonoMethod *method;
10146                         if (!(method = prop->property->get))
10147                                 method = prop->property->set;
10148                         g_assert (method);
10149
10150                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10151                         return_val_if_nok (error, NULL);
10152                 } 
10153 #ifndef DISABLE_REFLECTION_EMIT
10154                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10155                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10156                         return_val_if_nok (error, NULL);
10157                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10158                         return_val_if_nok (error, NULL);
10159                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10160                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10161                         MonoMethod *method = NULL;
10162                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10163                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10164                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10165                                 method = ((MonoReflectionMethod *)c->cb)->method;
10166                         else
10167                                 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));
10168
10169                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10170                         return_val_if_nok (error, NULL);
10171                 } 
10172 #endif
10173                 else {
10174                         char *type_name = mono_type_get_full_name (member_class);
10175                         mono_error_set_generic_error (error, "System", "NotSupportedException",
10176                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10177                                                       type_name);
10178                         g_free (type_name);
10179                         return NULL;
10180                 }
10181         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10182                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10183                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10184         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10185                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10186                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10187         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10188                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10189                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10190         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10191                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10192                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10193         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10194                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10195                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10196         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10197                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10198                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10199         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10200                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10201                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10202                 return_val_if_nok (error, NULL);
10203         } else { /* handle other types here... */
10204                 g_error ("get custom attrs not yet supported for %s", klass->name);
10205         }
10206
10207         return cinfo;
10208 }
10209
10210 /*
10211  * mono_reflection_get_custom_attrs_by_type:
10212  * @obj: a reflection object handle
10213  *
10214  * Return an array with all the custom attributes defined of the
10215  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10216  * of that type are returned. The objects are fully build. Return NULL if a loading error
10217  * occurs.
10218  */
10219 MonoArray*
10220 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10221 {
10222         MonoArray *result;
10223         MonoCustomAttrInfo *cinfo;
10224
10225         mono_error_init (error);
10226
10227         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10228         return_val_if_nok (error, NULL);
10229         if (cinfo) {
10230                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10231                 if (!result)
10232                         return NULL;
10233                 if (!cinfo->cached)
10234                         mono_custom_attrs_free (cinfo);
10235         } else {
10236                 mono_loader_assert_no_error ();
10237                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10238         }
10239
10240         return result;
10241 }
10242
10243 /*
10244  * mono_reflection_get_custom_attrs:
10245  * @obj: a reflection object handle
10246  *
10247  * Return an array with all the custom attributes defined of the
10248  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10249  * occurs.
10250  */
10251 MonoArray*
10252 mono_reflection_get_custom_attrs (MonoObject *obj)
10253 {
10254         MonoError error;
10255
10256         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10257 }
10258
10259 /*
10260  * mono_reflection_get_custom_attrs_data:
10261  * @obj: a reflection obj handle
10262  *
10263  * Returns an array of System.Reflection.CustomAttributeData,
10264  * which include information about attributes reflected on
10265  * types loaded using the Reflection Only methods
10266  */
10267 MonoArray*
10268 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10269 {
10270         MonoError error;
10271         MonoArray* result;
10272         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10273         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10274         return result;
10275 }
10276
10277 /*
10278  * mono_reflection_get_custom_attrs_data_checked:
10279  * @obj: a reflection obj handle
10280  * @error: set on error
10281  *
10282  * Returns an array of System.Reflection.CustomAttributeData,
10283  * which include information about attributes reflected on
10284  * types loaded using the Reflection Only methods
10285  */
10286 MonoArray*
10287 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10288 {
10289         MonoArray *result;
10290         MonoCustomAttrInfo *cinfo;
10291
10292         mono_error_init (error);
10293
10294         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10295         return_val_if_nok (error, NULL);
10296         if (cinfo) {
10297                 result = mono_custom_attrs_data_construct (cinfo, error);
10298                 return_val_if_nok (error, NULL);
10299                 if (!cinfo->cached)
10300                         mono_custom_attrs_free (cinfo);
10301         } else
10302                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10303
10304         if (mono_loader_get_last_error ())
10305                 mono_error_set_from_loader_error (error);
10306
10307         return result;
10308 }
10309
10310 static MonoReflectionType*
10311 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10312 {
10313         static MonoMethod *method_get_underlying_system_type = NULL;
10314         MonoReflectionType *rt;
10315         MonoMethod *usertype_method;
10316
10317         mono_error_init (error);
10318
10319         if (!method_get_underlying_system_type)
10320                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10321
10322         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10323
10324         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10325
10326         return rt;
10327 }
10328
10329
10330 static gboolean
10331 is_corlib_type (MonoClass *klass)
10332 {
10333         return klass->image == mono_defaults.corlib;
10334 }
10335
10336 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10337         static MonoClass *cached_class; \
10338         if (cached_class) \
10339                 return cached_class == _class; \
10340         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10341                 cached_class = _class; \
10342                 return TRUE; \
10343         } \
10344         return FALSE; \
10345 } while (0) \
10346
10347
10348 #ifndef DISABLE_REFLECTION_EMIT
10349 static gboolean
10350 is_sre_array (MonoClass *klass)
10351 {
10352         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10353 }
10354
10355 static gboolean
10356 is_sre_byref (MonoClass *klass)
10357 {
10358         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10359 }
10360
10361 static gboolean
10362 is_sre_pointer (MonoClass *klass)
10363 {
10364         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10365 }
10366
10367 static gboolean
10368 is_sre_generic_instance (MonoClass *klass)
10369 {
10370         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10371 }
10372
10373 static gboolean
10374 is_sre_type_builder (MonoClass *klass)
10375 {
10376         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10377 }
10378
10379 static gboolean
10380 is_sre_method_builder (MonoClass *klass)
10381 {
10382         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10383 }
10384
10385 static gboolean
10386 is_sre_ctor_builder (MonoClass *klass)
10387 {
10388         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10389 }
10390
10391 static gboolean
10392 is_sre_field_builder (MonoClass *klass)
10393 {
10394         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10395 }
10396
10397 static gboolean
10398 is_sre_method_on_tb_inst (MonoClass *klass)
10399 {
10400         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10401 }
10402
10403 static gboolean
10404 is_sre_ctor_on_tb_inst (MonoClass *klass)
10405 {
10406         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10407 }
10408
10409 MonoType*
10410 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10411 {
10412         MonoClass *klass;
10413         mono_error_init (error);
10414
10415         if (!ref)
10416                 return NULL;
10417         if (ref->type)
10418                 return ref->type;
10419
10420         if (is_usertype (ref)) {
10421                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10422                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10423                         return NULL;
10424                 if (ref->type)
10425                         return ref->type;
10426         }
10427
10428         klass = mono_object_class (ref);
10429
10430         if (is_sre_array (klass)) {
10431                 MonoType *res;
10432                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10433                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10434                 return_val_if_nok (error, NULL);
10435                 g_assert (base);
10436                 if (sre_array->rank == 0) //single dimentional array
10437                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10438                 else
10439                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10440                 sre_array->type.type = res;
10441                 return res;
10442         } else if (is_sre_byref (klass)) {
10443                 MonoType *res;
10444                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10445                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10446                 return_val_if_nok (error, NULL);
10447                 g_assert (base);
10448                 res = &mono_class_from_mono_type (base)->this_arg;
10449                 sre_byref->type.type = res;
10450                 return res;
10451         } else if (is_sre_pointer (klass)) {
10452                 MonoType *res;
10453                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10454                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10455                 return_val_if_nok (error, NULL);
10456                 g_assert (base);
10457                 res = &mono_ptr_class_get (base)->byval_arg;
10458                 sre_pointer->type.type = res;
10459                 return res;
10460         } else if (is_sre_generic_instance (klass)) {
10461                 MonoType *res, **types;
10462                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10463                 int i, count;
10464
10465                 count = mono_array_length (gclass->type_arguments);
10466                 types = g_new0 (MonoType*, count);
10467                 for (i = 0; i < count; ++i) {
10468                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10469                         types [i] = mono_reflection_type_get_handle (t, error);
10470                         if (!types[i] || !is_ok (error)) {
10471                                 g_free (types);
10472                                 return NULL;
10473                         }
10474                 }
10475
10476                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10477                 g_free (types);
10478                 g_assert (res);
10479                 gclass->type.type = res;
10480                 return res;
10481         }
10482
10483         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10484         return NULL;
10485 }
10486
10487 void
10488 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10489 {
10490         MonoError error;
10491         mono_reflection_type_get_handle (type, &error);
10492         mono_error_set_pending_exception (&error);
10493 }
10494
10495 void
10496 mono_reflection_register_with_runtime (MonoReflectionType *type)
10497 {
10498         MonoError error;
10499         MonoType *res = mono_reflection_type_get_handle (type, &error);
10500         mono_error_raise_exception (&error); /* FIXME don't raise here */
10501         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10502         MonoClass *klass;
10503
10504         if (!res)
10505                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10506
10507         klass = mono_class_from_mono_type (res);
10508
10509         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10510         mono_domain_lock (domain);
10511
10512         if (!image_is_dynamic (klass->image)) {
10513                 mono_class_setup_supertypes (klass);
10514         } else {
10515                 if (!domain->type_hash)
10516                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10517                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10518                 mono_g_hash_table_insert (domain->type_hash, res, type);
10519         }
10520         mono_domain_unlock (domain);
10521         mono_loader_unlock ();
10522 }
10523
10524 /**
10525  * LOCKING: Assumes the loader lock is held.
10526  */
10527 static MonoMethodSignature*
10528 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10529         MonoError error;
10530         MonoMethodSignature *sig;
10531         int count, i;
10532
10533         count = parameters? mono_array_length (parameters): 0;
10534
10535         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10536         sig->param_count = count;
10537         sig->sentinelpos = -1; /* FIXME */
10538         for (i = 0; i < count; ++i) {
10539                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10540                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10541         }
10542         return sig;
10543 }
10544
10545 /**
10546  * LOCKING: Assumes the loader lock is held.
10547  */
10548 static MonoMethodSignature*
10549 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10550         MonoMethodSignature *sig;
10551
10552         sig = parameters_to_signature (image, ctor->parameters);
10553         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10554         sig->ret = &mono_defaults.void_class->byval_arg;
10555         return sig;
10556 }
10557
10558 /**
10559  * LOCKING: Assumes the loader lock is held.
10560  */
10561 static MonoMethodSignature*
10562 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10563         MonoError error;
10564         MonoMethodSignature *sig;
10565
10566         sig = parameters_to_signature (image, method->parameters);
10567         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10568         if (method->rtype) {
10569                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10570                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10571         } else {
10572                 sig->ret = &mono_defaults.void_class->byval_arg;
10573         }
10574         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10575         return sig;
10576 }
10577
10578 static MonoMethodSignature*
10579 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10580         MonoError error;
10581         MonoMethodSignature *sig;
10582
10583         sig = parameters_to_signature (NULL, method->parameters);
10584         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10585         if (method->rtype) {
10586                 sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
10587                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10588         } else {
10589                 sig->ret = &mono_defaults.void_class->byval_arg;
10590         }
10591         sig->generic_param_count = 0;
10592         return sig;
10593 }
10594
10595 static void
10596 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10597 {
10598         MonoError error;
10599         MonoClass *klass = mono_object_class (prop);
10600         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10601                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10602                 *name = mono_string_to_utf8 (pb->name);
10603                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10604                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10605         } else {
10606                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10607                 *name = g_strdup (p->property->name);
10608                 if (p->property->get)
10609                         *type = mono_method_signature (p->property->get)->ret;
10610                 else
10611                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10612         }
10613 }
10614
10615 static void
10616 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10617 {
10618         MonoError error;
10619         MonoClass *klass = mono_object_class (field);
10620         if (strcmp (klass->name, "FieldBuilder") == 0) {
10621                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10622                 *name = mono_string_to_utf8 (fb->name);
10623                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10624                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10625         } else {
10626                 MonoReflectionField *f = (MonoReflectionField *)field;
10627                 *name = g_strdup (mono_field_get_name (f->field));
10628                 *type = f->field->type;
10629         }
10630 }
10631
10632 #else /* DISABLE_REFLECTION_EMIT */
10633
10634 void
10635 mono_reflection_register_with_runtime (MonoReflectionType *type)
10636 {
10637         /* This is empty */
10638 }
10639
10640 static gboolean
10641 is_sre_type_builder (MonoClass *klass)
10642 {
10643         return FALSE;
10644 }
10645
10646 static gboolean
10647 is_sre_generic_instance (MonoClass *klass)
10648 {
10649         return FALSE;
10650 }
10651
10652 static void
10653 init_type_builder_generics (MonoObject *type)
10654 {
10655 }
10656
10657 #endif /* !DISABLE_REFLECTION_EMIT */
10658
10659
10660 static gboolean
10661 is_sr_mono_field (MonoClass *klass)
10662 {
10663         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10664 }
10665
10666 static gboolean
10667 is_sr_mono_property (MonoClass *klass)
10668 {
10669         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10670 }
10671
10672 static gboolean
10673 is_sr_mono_method (MonoClass *klass)
10674 {
10675         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10676 }
10677
10678 static gboolean
10679 is_sr_mono_cmethod (MonoClass *klass)
10680 {
10681         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10682 }
10683
10684 static gboolean
10685 is_sr_mono_generic_method (MonoClass *klass)
10686 {
10687         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10688 }
10689
10690 static gboolean
10691 is_sr_mono_generic_cmethod (MonoClass *klass)
10692 {
10693         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10694 }
10695
10696 gboolean
10697 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10698 {
10699         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10700 }
10701
10702 static gboolean
10703 is_usertype (MonoReflectionType *ref)
10704 {
10705         MonoClass *klass = mono_object_class (ref);
10706         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10707 }
10708
10709 static MonoReflectionType*
10710 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10711 {
10712         mono_error_init (error);
10713         if (!type || type->type)
10714                 return type;
10715
10716         if (is_usertype (type)) {
10717                 type = mono_reflection_type_get_underlying_system_type (type, error);
10718                 return_val_if_nok (error, NULL);
10719                 if (is_usertype (type)) {
10720                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10721                         return NULL;
10722                 }
10723         }
10724
10725         return type;
10726 }
10727 /*
10728  * Encode a value in a custom attribute stream of bytes.
10729  * The value to encode is either supplied as an object in argument val
10730  * (valuetypes are boxed), or as a pointer to the data in the
10731  * argument argval.
10732  * @type represents the type of the value
10733  * @buffer is the start of the buffer
10734  * @p the current position in the buffer
10735  * @buflen contains the size of the buffer and is used to return the new buffer size
10736  * if this needs to be realloced.
10737  * @retbuffer and @retp return the start and the position of the buffer
10738  */
10739 static void
10740 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10741 {
10742         MonoError error;
10743         MonoTypeEnum simple_type;
10744         
10745         if ((p-buffer) + 10 >= *buflen) {
10746                 char *newbuf;
10747                 *buflen *= 2;
10748                 newbuf = (char *)g_realloc (buffer, *buflen);
10749                 p = newbuf + (p-buffer);
10750                 buffer = newbuf;
10751         }
10752         if (!argval)
10753                 argval = ((char*)arg + sizeof (MonoObject));
10754         simple_type = type->type;
10755 handle_enum:
10756         switch (simple_type) {
10757         case MONO_TYPE_BOOLEAN:
10758         case MONO_TYPE_U1:
10759         case MONO_TYPE_I1:
10760                 *p++ = *argval;
10761                 break;
10762         case MONO_TYPE_CHAR:
10763         case MONO_TYPE_U2:
10764         case MONO_TYPE_I2:
10765                 swap_with_size (p, argval, 2, 1);
10766                 p += 2;
10767                 break;
10768         case MONO_TYPE_U4:
10769         case MONO_TYPE_I4:
10770         case MONO_TYPE_R4:
10771                 swap_with_size (p, argval, 4, 1);
10772                 p += 4;
10773                 break;
10774         case MONO_TYPE_R8:
10775                 swap_with_size (p, argval, 8, 1);
10776                 p += 8;
10777                 break;
10778         case MONO_TYPE_U8:
10779         case MONO_TYPE_I8:
10780                 swap_with_size (p, argval, 8, 1);
10781                 p += 8;
10782                 break;
10783         case MONO_TYPE_VALUETYPE:
10784                 if (type->data.klass->enumtype) {
10785                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10786                         goto handle_enum;
10787                 } else {
10788                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10789                 }
10790                 break;
10791         case MONO_TYPE_STRING: {
10792                 char *str;
10793                 guint32 slen;
10794                 if (!arg) {
10795                         *p++ = 0xFF;
10796                         break;
10797                 }
10798                 str = mono_string_to_utf8 ((MonoString*)arg);
10799                 slen = strlen (str);
10800                 if ((p-buffer) + 10 + slen >= *buflen) {
10801                         char *newbuf;
10802                         *buflen *= 2;
10803                         *buflen += slen;
10804                         newbuf = (char *)g_realloc (buffer, *buflen);
10805                         p = newbuf + (p-buffer);
10806                         buffer = newbuf;
10807                 }
10808                 mono_metadata_encode_value (slen, p, &p);
10809                 memcpy (p, str, slen);
10810                 p += slen;
10811                 g_free (str);
10812                 break;
10813         }
10814         case MONO_TYPE_CLASS: {
10815                 char *str;
10816                 guint32 slen;
10817                 MonoType *arg_type;
10818                 if (!arg) {
10819                         *p++ = 0xFF;
10820                         break;
10821                 }
10822 handle_type:
10823                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10824                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10825                 str = type_get_qualified_name (arg_type, NULL);
10826                 slen = strlen (str);
10827                 if ((p-buffer) + 10 + slen >= *buflen) {
10828                         char *newbuf;
10829                         *buflen *= 2;
10830                         *buflen += slen;
10831                         newbuf = (char *)g_realloc (buffer, *buflen);
10832                         p = newbuf + (p-buffer);
10833                         buffer = newbuf;
10834                 }
10835                 mono_metadata_encode_value (slen, p, &p);
10836                 memcpy (p, str, slen);
10837                 p += slen;
10838                 g_free (str);
10839                 break;
10840         }
10841         case MONO_TYPE_SZARRAY: {
10842                 int len, i;
10843                 MonoClass *eclass, *arg_eclass;
10844
10845                 if (!arg) {
10846                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10847                         break;
10848                 }
10849                 len = mono_array_length ((MonoArray*)arg);
10850                 *p++ = len & 0xff;
10851                 *p++ = (len >> 8) & 0xff;
10852                 *p++ = (len >> 16) & 0xff;
10853                 *p++ = (len >> 24) & 0xff;
10854                 *retp = p;
10855                 *retbuffer = buffer;
10856                 eclass = type->data.klass;
10857                 arg_eclass = mono_object_class (arg)->element_class;
10858
10859                 if (!eclass) {
10860                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10861                         eclass = mono_defaults.object_class;
10862                 }
10863                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10864                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10865                         int elsize = mono_class_array_element_size (arg_eclass);
10866                         for (i = 0; i < len; ++i) {
10867                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10868                                 elptr += elsize;
10869                         }
10870                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10871                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10872                         int elsize = mono_class_array_element_size (eclass);
10873                         for (i = 0; i < len; ++i) {
10874                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10875                                 elptr += elsize;
10876                         }
10877                 } else {
10878                         for (i = 0; i < len; ++i) {
10879                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10880                         }
10881                 }
10882                 break;
10883         }
10884         case MONO_TYPE_OBJECT: {
10885                 MonoClass *klass;
10886                 char *str;
10887                 guint32 slen;
10888
10889                 /*
10890                  * The parameter type is 'object' but the type of the actual
10891                  * argument is not. So we have to add type information to the blob
10892                  * too. This is completely undocumented in the spec.
10893                  */
10894
10895                 if (arg == NULL) {
10896                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10897                         *p++ = 0xFF;
10898                         break;
10899                 }
10900                 
10901                 klass = mono_object_class (arg);
10902
10903                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10904                         *p++ = 0x50;
10905                         goto handle_type;
10906                 } else if (klass->enumtype) {
10907                         *p++ = 0x55;
10908                 } else if (klass == mono_defaults.string_class) {
10909                         simple_type = MONO_TYPE_STRING;
10910                         *p++ = 0x0E;
10911                         goto handle_enum;
10912                 } else if (klass->rank == 1) {
10913                         *p++ = 0x1D;
10914                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10915                                 /* See Partition II, Appendix B3 */
10916                                 *p++ = 0x51;
10917                         else
10918                                 *p++ = klass->element_class->byval_arg.type;
10919                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10920                         break;
10921                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10922                         *p++ = simple_type = klass->byval_arg.type;
10923                         goto handle_enum;
10924                 } else {
10925                         g_error ("unhandled type in custom attr");
10926                 }
10927                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10928                 slen = strlen (str);
10929                 if ((p-buffer) + 10 + slen >= *buflen) {
10930                         char *newbuf;
10931                         *buflen *= 2;
10932                         *buflen += slen;
10933                         newbuf = (char *)g_realloc (buffer, *buflen);
10934                         p = newbuf + (p-buffer);
10935                         buffer = newbuf;
10936                 }
10937                 mono_metadata_encode_value (slen, p, &p);
10938                 memcpy (p, str, slen);
10939                 p += slen;
10940                 g_free (str);
10941                 simple_type = mono_class_enum_basetype (klass)->type;
10942                 goto handle_enum;
10943         }
10944         default:
10945                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10946         }
10947         *retp = p;
10948         *retbuffer = buffer;
10949 }
10950
10951 static void
10952 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10953 {
10954         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10955                 char *str = type_get_qualified_name (type, NULL);
10956                 int slen = strlen (str);
10957
10958                 *p++ = 0x55;
10959                 /*
10960                  * This seems to be optional...
10961                  * *p++ = 0x80;
10962                  */
10963                 mono_metadata_encode_value (slen, p, &p);
10964                 memcpy (p, str, slen);
10965                 p += slen;
10966                 g_free (str);
10967         } else if (type->type == MONO_TYPE_OBJECT) {
10968                 *p++ = 0x51;
10969         } else if (type->type == MONO_TYPE_CLASS) {
10970                 /* it should be a type: encode_cattr_value () has the check */
10971                 *p++ = 0x50;
10972         } else {
10973                 mono_metadata_encode_value (type->type, p, &p);
10974                 if (type->type == MONO_TYPE_SZARRAY)
10975                         /* See the examples in Partition VI, Annex B */
10976                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10977         }
10978
10979         *retp = p;
10980 }
10981
10982 #ifndef DISABLE_REFLECTION_EMIT
10983 static void
10984 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10985 {
10986         int len;
10987         /* Preallocate a large enough buffer */
10988         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10989                 char *str = type_get_qualified_name (type, NULL);
10990                 len = strlen (str);
10991                 g_free (str);
10992         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10993                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10994                 len = strlen (str);
10995                 g_free (str);
10996         } else {
10997                 len = 0;
10998         }
10999         len += strlen (name);
11000
11001         if ((p-buffer) + 20 + len >= *buflen) {
11002                 char *newbuf;
11003                 *buflen *= 2;
11004                 *buflen += len;
11005                 newbuf = (char *)g_realloc (buffer, *buflen);
11006                 p = newbuf + (p-buffer);
11007                 buffer = newbuf;
11008         }
11009
11010         encode_field_or_prop_type (type, p, &p);
11011
11012         len = strlen (name);
11013         mono_metadata_encode_value (len, p, &p);
11014         memcpy (p, name, len);
11015         p += len;
11016         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11017         *retp = p;
11018         *retbuffer = buffer;
11019 }
11020
11021 /*
11022  * mono_reflection_get_custom_attrs_blob:
11023  * @ctor: custom attribute constructor
11024  * @ctorArgs: arguments o the constructor
11025  * @properties:
11026  * @propValues:
11027  * @fields:
11028  * @fieldValues:
11029  * 
11030  * Creates the blob of data that needs to be saved in the metadata and that represents
11031  * the custom attributed described by @ctor, @ctorArgs etc.
11032  * Returns: a Byte array representing the blob of data.
11033  */
11034 MonoArray*
11035 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11036 {
11037         MonoArray *result;
11038         MonoMethodSignature *sig;
11039         MonoObject *arg;
11040         char *buffer, *p;
11041         guint32 buflen, i;
11042
11043         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11044                 /* sig is freed later so allocate it in the heap */
11045                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11046         } else {
11047                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11048         }
11049
11050         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11051         buflen = 256;
11052         p = buffer = (char *)g_malloc (buflen);
11053         /* write the prolog */
11054         *p++ = 1;
11055         *p++ = 0;
11056         for (i = 0; i < sig->param_count; ++i) {
11057                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11058                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11059         }
11060         i = 0;
11061         if (properties)
11062                 i += mono_array_length (properties);
11063         if (fields)
11064                 i += mono_array_length (fields);
11065         *p++ = i & 0xff;
11066         *p++ = (i >> 8) & 0xff;
11067         if (properties) {
11068                 MonoObject *prop;
11069                 for (i = 0; i < mono_array_length (properties); ++i) {
11070                         MonoType *ptype;
11071                         char *pname;
11072
11073                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11074                         get_prop_name_and_type (prop, &pname, &ptype);
11075                         *p++ = 0x54; /* PROPERTY signature */
11076                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11077                         g_free (pname);
11078                 }
11079         }
11080
11081         if (fields) {
11082                 MonoObject *field;
11083                 for (i = 0; i < mono_array_length (fields); ++i) {
11084                         MonoType *ftype;
11085                         char *fname;
11086
11087                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11088                         get_field_name_and_type (field, &fname, &ftype);
11089                         *p++ = 0x53; /* FIELD signature */
11090                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11091                         g_free (fname);
11092                 }
11093         }
11094
11095         g_assert (p - buffer <= buflen);
11096         buflen = p - buffer;
11097         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11098         p = mono_array_addr (result, char, 0);
11099         memcpy (p, buffer, buflen);
11100         g_free (buffer);
11101         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11102                 g_free (sig);
11103         return result;
11104 }
11105
11106 /*
11107  * mono_reflection_setup_internal_class:
11108  * @tb: a TypeBuilder object
11109  *
11110  * Creates a MonoClass that represents the TypeBuilder.
11111  * This is a trick that lets us simplify a lot of reflection code
11112  * (and will allow us to support Build and Run assemblies easier).
11113  */
11114 void
11115 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11116 {
11117         MonoError error;
11118         MonoClass *klass, *parent;
11119
11120         RESOLVE_TYPE (tb->parent, &error);
11121         mono_error_raise_exception (&error); /* FIXME don't raise here */
11122
11123         mono_loader_lock ();
11124
11125         if (tb->parent) {
11126                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11127                 if (!is_ok (&error)) {
11128                         mono_loader_unlock ();
11129                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11130                 }
11131                 /* check so we can compile corlib correctly */
11132                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11133                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11134                         parent = parent_type->data.klass;
11135                 } else {
11136                         parent = mono_class_from_mono_type (parent_type);
11137                 }
11138         } else {
11139                 parent = NULL;
11140         }
11141         
11142         /* the type has already being created: it means we just have to change the parent */
11143         if (tb->type.type) {
11144                 klass = mono_class_from_mono_type (tb->type.type);
11145                 klass->parent = NULL;
11146                 /* fool mono_class_setup_parent */
11147                 klass->supertypes = NULL;
11148                 mono_class_setup_parent (klass, parent);
11149                 mono_class_setup_mono_type (klass);
11150                 mono_loader_unlock ();
11151                 return;
11152         }
11153
11154         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11155
11156         klass->image = &tb->module->dynamic_image->image;
11157
11158         klass->inited = 1; /* we lie to the runtime */
11159         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11160         if (!mono_error_ok (&error))
11161                 goto failure;
11162         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11163         if (!mono_error_ok (&error))
11164                 goto failure;
11165         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11166         klass->flags = tb->attrs;
11167         
11168         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11169
11170         klass->element_class = klass;
11171
11172         if (mono_class_get_ref_info (klass) == NULL) {
11173
11174                 mono_class_set_ref_info (klass, tb);
11175
11176                 /* Put into cache so mono_class_get_checked () will find it.
11177                 Skip nested types as those should not be available on the global scope. */
11178                 if (!tb->nesting_type)
11179                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11180
11181                 /*
11182                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11183                 by performing a mono_class_get which does the full resolution.
11184
11185                 Working around this semantics would require us to write a lot of code for no clear advantage.
11186                 */
11187                 mono_image_append_class_to_reflection_info_set (klass);
11188         } else {
11189                 g_assert (mono_class_get_ref_info (klass) == tb);
11190         }
11191
11192         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11193
11194         if (parent != NULL) {
11195                 mono_class_setup_parent (klass, parent);
11196         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11197                 const char *old_n = klass->name;
11198                 /* trick to get relative numbering right when compiling corlib */
11199                 klass->name = "BuildingObject";
11200                 mono_class_setup_parent (klass, mono_defaults.object_class);
11201                 klass->name = old_n;
11202         }
11203
11204         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11205                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11206                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11207                 klass->instance_size = sizeof (MonoObject);
11208                 klass->size_inited = 1;
11209                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11210         }
11211
11212         mono_class_setup_mono_type (klass);
11213
11214         mono_class_setup_supertypes (klass);
11215
11216         /*
11217          * FIXME: handle interfaces.
11218          */
11219
11220         tb->type.type = &klass->byval_arg;
11221
11222         if (tb->nesting_type) {
11223                 g_assert (tb->nesting_type->type);
11224                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11225                 if (!is_ok (&error)) goto failure;
11226                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11227         }
11228
11229         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11230
11231         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11232         
11233         mono_loader_unlock ();
11234         return;
11235
11236 failure:
11237         mono_loader_unlock ();
11238         mono_error_raise_exception (&error);
11239 }
11240
11241 /*
11242  * mono_reflection_setup_generic_class:
11243  * @tb: a TypeBuilder object
11244  *
11245  * Setup the generic class before adding the first generic parameter.
11246  */
11247 void
11248 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11249 {
11250 }
11251
11252 /*
11253  * mono_reflection_create_generic_class:
11254  * @tb: a TypeBuilder object
11255  *
11256  * Creates the generic class after all generic parameters have been added.
11257  */
11258 void
11259 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11260 {
11261         MonoError error;
11262         MonoClass *klass;
11263         int count, i;
11264
11265         klass = mono_class_from_mono_type (tb->type.type);
11266
11267         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11268
11269         if (klass->generic_container || (count == 0))
11270                 return;
11271
11272         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11273
11274         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11275
11276         klass->generic_container->owner.klass = klass;
11277         klass->generic_container->type_argc = count;
11278         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11279
11280         klass->is_generic = 1;
11281
11282         for (i = 0; i < count; i++) {
11283                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11284                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11285                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11286                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11287                 klass->generic_container->type_params [i] = *param;
11288                 /*Make sure we are a diferent type instance */
11289                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11290                 klass->generic_container->type_params [i].info.pklass = NULL;
11291                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11292
11293                 g_assert (klass->generic_container->type_params [i].param.owner);
11294         }
11295
11296         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11297 }
11298
11299 /*
11300  * mono_reflection_create_internal_class:
11301  * @tb: a TypeBuilder object
11302  *
11303  * Actually create the MonoClass that is associated with the TypeBuilder.
11304  */
11305 void
11306 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11307 {
11308         MonoError error;
11309         MonoClass *klass;
11310
11311         klass = mono_class_from_mono_type (tb->type.type);
11312
11313         mono_loader_lock ();
11314         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11315                 MonoReflectionFieldBuilder *fb;
11316                 MonoClass *ec;
11317                 MonoType *enum_basetype;
11318
11319                 g_assert (tb->fields != NULL);
11320                 g_assert (mono_array_length (tb->fields) >= 1);
11321
11322                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11323
11324                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11325                 if (!is_ok (&error)) {
11326                         mono_loader_unlock ();
11327                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11328                 }
11329                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11330                         mono_loader_unlock ();
11331                         return;
11332                 }
11333
11334                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11335                 if (!is_ok (&error)) {
11336                         mono_loader_unlock ();
11337                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11338                 }
11339                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11340                 if (!klass->element_class)
11341                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11342
11343                 /*
11344                  * get the element_class from the current corlib.
11345                  */
11346                 ec = default_class_from_mono_type (enum_basetype);
11347                 klass->instance_size = ec->instance_size;
11348                 klass->size_inited = 1;
11349                 /* 
11350                  * this is almost safe to do with enums and it's needed to be able
11351                  * to create objects of the enum type (for use in SetConstant).
11352                  */
11353                 /* FIXME: Does this mean enums can't have method overrides ? */
11354                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11355         }
11356         mono_loader_unlock ();
11357 }
11358
11359 static MonoMarshalSpec*
11360 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11361                                                                 MonoReflectionMarshal *minfo)
11362 {
11363         MonoError error;
11364         MonoMarshalSpec *res;
11365
11366         res = image_g_new0 (image, MonoMarshalSpec, 1);
11367         res->native = (MonoMarshalNative)minfo->type;
11368
11369         switch (minfo->type) {
11370         case MONO_NATIVE_LPARRAY:
11371                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11372                 if (minfo->has_size) {
11373                         res->data.array_data.param_num = minfo->param_num;
11374                         res->data.array_data.num_elem = minfo->count;
11375                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11376                 }
11377                 else {
11378                         res->data.array_data.param_num = -1;
11379                         res->data.array_data.num_elem = -1;
11380                         res->data.array_data.elem_mult = -1;
11381                 }
11382                 break;
11383
11384         case MONO_NATIVE_BYVALTSTR:
11385         case MONO_NATIVE_BYVALARRAY:
11386                 res->data.array_data.num_elem = minfo->count;
11387                 break;
11388
11389         case MONO_NATIVE_CUSTOM:
11390                 if (minfo->marshaltyperef) {
11391                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11392                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11393                         res->data.custom_data.custom_name =
11394                                 type_get_fully_qualified_name (marshaltyperef);
11395                 }
11396                 if (minfo->mcookie)
11397                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11398                 break;
11399
11400         default:
11401                 break;
11402         }
11403
11404         return res;
11405 }
11406 #endif /* !DISABLE_REFLECTION_EMIT */
11407
11408 MonoReflectionMarshalAsAttribute*
11409 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11410                                                         MonoMarshalSpec *spec, MonoError *error)
11411 {
11412         MonoReflectionType *rt;
11413         MonoReflectionMarshalAsAttribute *minfo;
11414         MonoType *mtype;
11415
11416         mono_error_init (error);
11417         
11418         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11419         if (!minfo)
11420                 return NULL;
11421         minfo->utype = spec->native;
11422
11423         switch (minfo->utype) {
11424         case MONO_NATIVE_LPARRAY:
11425                 minfo->array_subtype = spec->data.array_data.elem_type;
11426                 minfo->size_const = spec->data.array_data.num_elem;
11427                 if (spec->data.array_data.param_num != -1)
11428                         minfo->size_param_index = spec->data.array_data.param_num;
11429                 break;
11430
11431         case MONO_NATIVE_BYVALTSTR:
11432         case MONO_NATIVE_BYVALARRAY:
11433                 minfo->size_const = spec->data.array_data.num_elem;
11434                 break;
11435
11436         case MONO_NATIVE_CUSTOM:
11437                 if (spec->data.custom_data.custom_name) {
11438                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11439                         if (mtype) {
11440                                 rt = mono_type_get_object_checked (domain, mtype, error);
11441                                 if (!rt)
11442                                         return NULL;
11443
11444                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11445                         }
11446
11447                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11448                 }
11449                 if (spec->data.custom_data.cookie)
11450                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11451                 break;
11452
11453         default:
11454                 break;
11455         }
11456
11457         return minfo;
11458 }
11459
11460 #ifndef DISABLE_REFLECTION_EMIT
11461 static MonoMethod*
11462 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11463                                          ReflectionMethodBuilder *rmb,
11464                                          MonoMethodSignature *sig)
11465 {
11466         MonoError error;
11467         MonoMethod *m;
11468         MonoMethodWrapper *wrapperm;
11469         MonoMarshalSpec **specs;
11470         MonoReflectionMethodAux *method_aux;
11471         MonoImage *image;
11472         gboolean dynamic;
11473         int i;
11474
11475         mono_error_init (&error);
11476         /*
11477          * Methods created using a MethodBuilder should have their memory allocated
11478          * inside the image mempool, while dynamic methods should have their memory
11479          * malloc'd.
11480          */
11481         dynamic = rmb->refs != NULL;
11482         image = dynamic ? NULL : klass->image;
11483
11484         if (!dynamic)
11485                 g_assert (!klass->generic_class);
11486
11487         mono_loader_lock ();
11488
11489         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11490                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11491                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11492         else
11493                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11494
11495         wrapperm = (MonoMethodWrapper*)m;
11496
11497         m->dynamic = dynamic;
11498         m->slot = -1;
11499         m->flags = rmb->attrs;
11500         m->iflags = rmb->iattrs;
11501         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11502         m->klass = klass;
11503         m->signature = sig;
11504         m->sre_method = TRUE;
11505         m->skip_visibility = rmb->skip_visibility;
11506         if (rmb->table_idx)
11507                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11508
11509         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11510                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11511                         m->string_ctor = 1;
11512
11513                 m->signature->pinvoke = 1;
11514         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11515                 m->signature->pinvoke = 1;
11516
11517                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11518
11519                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11520                 g_assert (mono_error_ok (&error));
11521                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11522                 g_assert (mono_error_ok (&error));
11523                 
11524                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11525
11526                 if (image_is_dynamic (klass->image))
11527                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11528
11529                 mono_loader_unlock ();
11530
11531                 return m;
11532         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11533                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11534                 MonoMethodHeader *header;
11535                 guint32 code_size;
11536                 gint32 max_stack, i;
11537                 gint32 num_locals = 0;
11538                 gint32 num_clauses = 0;
11539                 guint8 *code;
11540
11541                 if (rmb->ilgen) {
11542                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11543                         code_size = rmb->ilgen->code_len;
11544                         max_stack = rmb->ilgen->max_stack;
11545                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11546                         if (rmb->ilgen->ex_handlers)
11547                                 num_clauses = method_count_clauses (rmb->ilgen);
11548                 } else {
11549                         if (rmb->code) {
11550                                 code = mono_array_addr (rmb->code, guint8, 0);
11551                                 code_size = mono_array_length (rmb->code);
11552                                 /* we probably need to run a verifier on the code... */
11553                                 max_stack = 8; 
11554                         }
11555                         else {
11556                                 code = NULL;
11557                                 code_size = 0;
11558                                 max_stack = 8;
11559                         }
11560                 }
11561
11562                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11563                 header->code_size = code_size;
11564                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11565                 memcpy ((char*)header->code, code, code_size);
11566                 header->max_stack = max_stack;
11567                 header->init_locals = rmb->init_locals;
11568                 header->num_locals = num_locals;
11569
11570                 for (i = 0; i < num_locals; ++i) {
11571                         MonoReflectionLocalBuilder *lb = 
11572                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11573
11574                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11575                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11576                         mono_error_assert_ok (&error);
11577                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11578                 }
11579
11580                 header->num_clauses = num_clauses;
11581                 if (num_clauses) {
11582                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11583                                  rmb->ilgen, num_clauses);
11584                 }
11585
11586                 wrapperm->header = header;
11587         }
11588
11589         if (rmb->generic_params) {
11590                 int count = mono_array_length (rmb->generic_params);
11591                 MonoGenericContainer *container = rmb->generic_container;
11592
11593                 g_assert (container);
11594
11595                 container->type_argc = count;
11596                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11597                 container->owner.method = m;
11598                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11599
11600                 m->is_generic = TRUE;
11601                 mono_method_set_generic_container (m, container);
11602
11603                 for (i = 0; i < count; i++) {
11604                         MonoReflectionGenericParam *gp =
11605                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11606                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11607                         mono_error_assert_ok (&error);
11608                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11609                         container->type_params [i] = *param;
11610                 }
11611
11612                 /*
11613                  * The method signature might have pointers to generic parameters that belong to other methods.
11614                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11615                  * generic parameters.
11616                  */
11617                 for (i = 0; i < m->signature->param_count; ++i) {
11618                         MonoType *t = m->signature->params [i];
11619                         if (t->type == MONO_TYPE_MVAR) {
11620                                 MonoGenericParam *gparam =  t->data.generic_param;
11621                                 if (gparam->num < count) {
11622                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11623                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11624                                 }
11625
11626                         }
11627                 }
11628
11629                 if (klass->generic_container) {
11630                         container->parent = klass->generic_container;
11631                         container->context.class_inst = klass->generic_container->context.class_inst;
11632                 }
11633                 container->context.method_inst = mono_get_shared_generic_inst (container);
11634         }
11635
11636         if (rmb->refs) {
11637                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11638                 int i;
11639                 void **data;
11640
11641                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11642
11643                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11644                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11645                 for (i = 0; i < rmb->nrefs; ++i)
11646                         data [i + 1] = rmb->refs [i];
11647         }
11648
11649         method_aux = NULL;
11650
11651         /* Parameter info */
11652         if (rmb->pinfo) {
11653                 if (!method_aux)
11654                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11655                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11656                 for (i = 0; i <= m->signature->param_count; ++i) {
11657                         MonoReflectionParamBuilder *pb;
11658                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11659                                 if ((i > 0) && (pb->attrs)) {
11660                                         /* Make a copy since it might point to a shared type structure */
11661                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11662                                         m->signature->params [i - 1]->attrs = pb->attrs;
11663                                 }
11664
11665                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11666                                         MonoDynamicImage *assembly;
11667                                         guint32 idx, len;
11668                                         MonoTypeEnum def_type;
11669                                         char *p;
11670                                         const char *p2;
11671
11672                                         if (!method_aux->param_defaults) {
11673                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11674                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11675                                         }
11676                                         assembly = (MonoDynamicImage*)klass->image;
11677                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11678                                         /* Copy the data from the blob since it might get realloc-ed */
11679                                         p = assembly->blob.data + idx;
11680                                         len = mono_metadata_decode_blob_size (p, &p2);
11681                                         len += p2 - p;
11682                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11683                                         method_aux->param_default_types [i] = def_type;
11684                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11685                                 }
11686
11687                                 if (pb->name) {
11688                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11689                                         g_assert (mono_error_ok (&error));
11690                                 }
11691                                 if (pb->cattrs) {
11692                                         if (!method_aux->param_cattr)
11693                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11694                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11695                                 }
11696                         }
11697                 }
11698         }
11699
11700         /* Parameter marshalling */
11701         specs = NULL;
11702         if (rmb->pinfo)         
11703                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11704                         MonoReflectionParamBuilder *pb;
11705                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11706                                 if (pb->marshal_info) {
11707                                         if (specs == NULL)
11708                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11709                                         specs [pb->position] = 
11710                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11711                                 }
11712                         }
11713                 }
11714         if (specs != NULL) {
11715                 if (!method_aux)
11716                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11717                 method_aux->param_marshall = specs;
11718         }
11719
11720         if (image_is_dynamic (klass->image) && method_aux)
11721                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11722
11723         mono_loader_unlock ();
11724
11725         return m;
11726 }       
11727
11728 static MonoMethod*
11729 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11730 {
11731         ReflectionMethodBuilder rmb;
11732         MonoMethodSignature *sig;
11733
11734         mono_loader_lock ();
11735         sig = ctor_builder_to_signature (klass->image, mb);
11736         mono_loader_unlock ();
11737
11738         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11739                 return NULL;
11740
11741         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11742         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11743
11744         /* If we are in a generic class, we might be called multiple times from inflate_method */
11745         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11746                 /* ilgen is no longer needed */
11747                 mb->ilgen = NULL;
11748         }
11749
11750         return mb->mhandle;
11751 }
11752
11753 static MonoMethod*
11754 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11755 {
11756         ReflectionMethodBuilder rmb;
11757         MonoMethodSignature *sig;
11758
11759         mono_error_init (error);
11760
11761         mono_loader_lock ();
11762         sig = method_builder_to_signature (klass->image, mb);
11763         mono_loader_unlock ();
11764
11765         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11766                 return NULL;
11767
11768         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11769         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11770
11771         /* If we are in a generic class, we might be called multiple times from inflate_method */
11772         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11773                 /* ilgen is no longer needed */
11774                 mb->ilgen = NULL;
11775         }
11776         return mb->mhandle;
11777 }
11778
11779 static MonoClassField*
11780 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11781 {
11782         MonoClassField *field;
11783         MonoType *custom;
11784         MonoError error;
11785
11786         field = g_new0 (MonoClassField, 1);
11787
11788         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11789         g_assert (mono_error_ok (&error));
11790         if (fb->attrs || fb->modreq || fb->modopt) {
11791                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11792                 if (!is_ok (&error)) {
11793                         g_free (field);
11794                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11795                 }
11796                 field->type = mono_metadata_type_dup (NULL, type);
11797                 field->type->attrs = fb->attrs;
11798
11799                 g_assert (image_is_dynamic (klass->image));
11800                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11801                 g_free (field->type);
11802                 field->type = mono_metadata_type_dup (klass->image, custom);
11803                 g_free (custom);
11804         } else {
11805                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11806                 if (!is_ok (&error)) {
11807                         g_free (field);
11808                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11809                 }
11810         }
11811         if (fb->offset != -1)
11812                 field->offset = fb->offset;
11813         field->parent = klass;
11814         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11815
11816         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11817
11818         return field;
11819 }
11820 #endif
11821
11822 MonoType*
11823 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11824 {
11825         MonoError error;
11826         MonoClass *klass;
11827         MonoReflectionTypeBuilder *tb = NULL;
11828         gboolean is_dynamic = FALSE;
11829         MonoClass *geninst;
11830
11831         mono_loader_lock ();
11832
11833         if (is_sre_type_builder (mono_object_class (type))) {
11834                 tb = (MonoReflectionTypeBuilder *) type;
11835
11836                 is_dynamic = TRUE;
11837         } else if (is_sre_generic_instance (mono_object_class (type))) {
11838                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11839                 MonoReflectionType *gtd = rgi->generic_type;
11840
11841                 if (is_sre_type_builder (mono_object_class (gtd))) {
11842                         tb = (MonoReflectionTypeBuilder *)gtd;
11843                         is_dynamic = TRUE;
11844                 }
11845         }
11846
11847         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11848         if (tb && tb->generic_container)
11849                 mono_reflection_create_generic_class (tb);
11850
11851         MonoType *t = mono_reflection_type_get_handle (type, &error);
11852         mono_error_raise_exception (&error); /* FIXME don't raise here */
11853
11854         klass = mono_class_from_mono_type (t);
11855         if (!klass->generic_container) {
11856                 mono_loader_unlock ();
11857                 return NULL;
11858         }
11859
11860         if (klass->wastypebuilder) {
11861                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11862
11863                 is_dynamic = TRUE;
11864         }
11865
11866         mono_loader_unlock ();
11867
11868         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11869
11870         return &geninst->byval_arg;
11871 }
11872
11873 MonoClass*
11874 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11875 {
11876         MonoGenericClass *gclass;
11877         MonoGenericInst *inst;
11878
11879         g_assert (klass->generic_container);
11880
11881         inst = mono_metadata_get_generic_inst (type_argc, types);
11882         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11883
11884         return mono_generic_class_get_class (gclass);
11885 }
11886
11887 MonoReflectionMethod*
11888 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11889 {
11890         MonoError error;
11891         MonoClass *klass;
11892         MonoMethod *method, *inflated;
11893         MonoMethodInflated *imethod;
11894         MonoGenericContext tmp_context;
11895         MonoGenericInst *ginst;
11896         MonoType **type_argv;
11897         int count, i;
11898
11899         /*FIXME but this no longer should happen*/
11900         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11901 #ifndef DISABLE_REFLECTION_EMIT
11902                 MonoReflectionMethodBuilder *mb = NULL;
11903                 MonoType *tb;
11904                 MonoClass *klass;
11905
11906                 mb = (MonoReflectionMethodBuilder *) rmethod;
11907                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11908                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11909                 klass = mono_class_from_mono_type (tb);
11910
11911                 method = methodbuilder_to_mono_method (klass, mb, &error);
11912                 if (!method)
11913                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11914 #else
11915                 g_assert_not_reached ();
11916                 method = NULL;
11917 #endif
11918         } else {
11919                 method = rmethod->method;
11920         }
11921
11922         klass = method->klass;
11923
11924         if (method->is_inflated)
11925                 method = ((MonoMethodInflated *) method)->declaring;
11926
11927         count = mono_method_signature (method)->generic_param_count;
11928         if (count != mono_array_length (types))
11929                 return NULL;
11930
11931         type_argv = g_new0 (MonoType *, count);
11932         for (i = 0; i < count; i++) {
11933                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11934                 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
11935                 if (!is_ok (&error)) {
11936                         g_free (type_argv);
11937                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11938                 }
11939         }
11940         ginst = mono_metadata_get_generic_inst (count, type_argv);
11941         g_free (type_argv);
11942
11943         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11944         tmp_context.method_inst = ginst;
11945
11946         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11947         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11948         imethod = (MonoMethodInflated *) inflated;
11949
11950         /*FIXME but I think this is no longer necessary*/
11951         if (image_is_dynamic (method->klass->image)) {
11952                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11953                 /*
11954                  * This table maps metadata structures representing inflated methods/fields
11955                  * to the reflection objects representing their generic definitions.
11956                  */
11957                 mono_image_lock ((MonoImage*)image);
11958                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11959                 mono_image_unlock ((MonoImage*)image);
11960         }
11961
11962         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11963                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11964         
11965         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11966         mono_error_raise_exception (&error); /* FIXME don't raise here */
11967         return ret;
11968 }
11969
11970 #ifndef DISABLE_REFLECTION_EMIT
11971
11972 static MonoMethod *
11973 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11974 {
11975         MonoMethodInflated *imethod;
11976         MonoGenericContext *context;
11977         int i;
11978
11979         /*
11980          * With generic code sharing the klass might not be inflated.
11981          * This can happen because classes inflated with their own
11982          * type arguments are "normalized" to the uninflated class.
11983          */
11984         if (!klass->generic_class)
11985                 return method;
11986
11987         context = mono_class_get_context (klass);
11988
11989         if (klass->method.count && klass->methods) {
11990                 /* Find the already created inflated method */
11991                 for (i = 0; i < klass->method.count; ++i) {
11992                         g_assert (klass->methods [i]->is_inflated);
11993                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11994                                 break;
11995                 }
11996                 g_assert (i < klass->method.count);
11997                 imethod = (MonoMethodInflated*)klass->methods [i];
11998         } else {
11999                 MonoError error;
12000                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12001                 mono_error_assert_ok (&error);
12002         }
12003
12004         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12005                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12006
12007                 mono_image_lock ((MonoImage*)image);
12008                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12009                 mono_image_unlock ((MonoImage*)image);
12010         }
12011         return (MonoMethod *) imethod;
12012 }
12013
12014 static MonoMethod *
12015 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12016 {
12017         MonoMethod *method;
12018         MonoClass *gklass;
12019
12020         mono_error_init (error);
12021
12022         MonoClass *type_class = mono_object_class (type);
12023
12024         if (is_sre_generic_instance (type_class)) {
12025                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12026                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12027                 return_val_if_nok (error, NULL);
12028                 gklass = mono_class_from_mono_type (generic_type);
12029         } else if (is_sre_type_builder (type_class)) {
12030                 MonoType *t = mono_reflection_type_get_handle (type, error);
12031                 return_val_if_nok (error, NULL);
12032                 gklass = mono_class_from_mono_type (t);
12033         } else if (type->type) {
12034                 gklass = mono_class_from_mono_type (type->type);
12035                 gklass = mono_class_get_generic_type_definition (gklass);
12036         } else {
12037                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12038         }
12039
12040         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12041                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12042                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12043                 else {
12044                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12045                         if (!method)
12046                                 return NULL;
12047                 }
12048         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12049                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12050                 if (!method)
12051                         return NULL;
12052         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12053                 method = ((MonoReflectionMethod *) obj)->method;
12054         else {
12055                 method = NULL; /* prevent compiler warning */
12056                 g_error ("can't handle type %s", obj->vtable->klass->name);
12057         }
12058
12059         MonoType *t = mono_reflection_type_get_handle (type, error);
12060         return_val_if_nok (error, NULL);
12061         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12062 }
12063
12064 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12065 void
12066 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12067 {
12068         MonoError error;
12069         MonoGenericClass *gclass;
12070         MonoDynamicGenericClass *dgclass;
12071         MonoClass *klass, *gklass;
12072         MonoType *gtype;
12073         int i;
12074
12075         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12076         mono_error_raise_exception (&error); /* FIXME don't raise here */
12077         klass = mono_class_from_mono_type (gtype);
12078         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12079         gclass = gtype->data.generic_class;
12080
12081         if (!gclass->is_dynamic)
12082                 return;
12083
12084         dgclass = (MonoDynamicGenericClass *) gclass;
12085
12086         if (dgclass->initialized)
12087                 return;
12088
12089         gklass = gclass->container_class;
12090         mono_class_init (gklass);
12091
12092         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12093
12094         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12095         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12096         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12097
12098         for (i = 0; i < dgclass->count_fields; i++) {
12099                 MonoError error;
12100                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12101                 MonoClassField *field, *inflated_field = NULL;
12102
12103                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12104                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12105                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12106                         field = ((MonoReflectionField *) obj)->field;
12107                 else {
12108                         field = NULL; /* prevent compiler warning */
12109                         g_assert_not_reached ();
12110                 }
12111
12112                 dgclass->fields [i] = *field;
12113                 dgclass->fields [i].parent = klass;
12114                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12115                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12116                 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12117                 dgclass->field_generic_types [i] = field->type;
12118                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12119                 dgclass->field_objects [i] = obj;
12120
12121                 if (inflated_field) {
12122                         g_free (inflated_field);
12123                 } else {
12124                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12125                 }
12126         }
12127
12128         dgclass->initialized = TRUE;
12129 }
12130
12131 void
12132 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12133 {
12134         MonoDynamicGenericClass *dgclass;
12135         int i;
12136
12137         g_assert (gclass->is_dynamic);
12138
12139         dgclass = (MonoDynamicGenericClass *)gclass;
12140
12141         for (i = 0; i < dgclass->count_fields; ++i) {
12142                 MonoClassField *field = dgclass->fields + i;
12143                 mono_metadata_free_type (field->type);
12144                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12145         }
12146 }
12147
12148 static void
12149 fix_partial_generic_class (MonoClass *klass)
12150 {
12151         MonoClass *gklass = klass->generic_class->container_class;
12152         MonoDynamicGenericClass *dgclass;
12153         int i;
12154
12155         if (klass->wastypebuilder)
12156                 return;
12157
12158         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12159         if (klass->parent != gklass->parent) {
12160                 MonoError error;
12161                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12162                 if (mono_error_ok (&error)) {
12163                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12164                         mono_metadata_free_type (parent_type);
12165                         if (parent != klass->parent) {
12166                                 /*fool mono_class_setup_parent*/
12167                                 klass->supertypes = NULL;
12168                                 mono_class_setup_parent (klass, parent);
12169                         }
12170                 } else {
12171                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12172                         mono_error_cleanup (&error);
12173                         if (gklass->wastypebuilder)
12174                                 klass->wastypebuilder = TRUE;
12175                         return;
12176                 }
12177         }
12178
12179         if (!dgclass->initialized)
12180                 return;
12181
12182         if (klass->method.count != gklass->method.count) {
12183                 klass->method.count = gklass->method.count;
12184                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12185
12186                 for (i = 0; i < klass->method.count; i++) {
12187                         MonoError error;
12188                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12189                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12190                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12191                 }
12192         }
12193
12194         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12195                 klass->interface_count = gklass->interface_count;
12196                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12197                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12198
12199                 for (i = 0; i < gklass->interface_count; ++i) {
12200                         MonoError error;
12201                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12202                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12203
12204                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12205                         mono_metadata_free_type (iface_type);
12206
12207                         ensure_runtime_vtable (klass->interfaces [i], &error);
12208                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12209                 }
12210                 klass->interfaces_inited = 1;
12211         }
12212
12213         if (klass->field.count != gklass->field.count) {
12214                 klass->field.count = gklass->field.count;
12215                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12216
12217                 for (i = 0; i < klass->field.count; i++) {
12218                         MonoError error;
12219                         klass->fields [i] = gklass->fields [i];
12220                         klass->fields [i].parent = klass;
12221                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12222                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12223                 }
12224         }
12225
12226         /*We can only finish with this klass once it's parent has as well*/
12227         if (gklass->wastypebuilder)
12228                 klass->wastypebuilder = TRUE;
12229         return;
12230 }
12231
12232 /**
12233  * ensure_generic_class_runtime_vtable:
12234  * @klass a generic class
12235  * @error set on error
12236  *
12237  * Ensures that the generic container of @klass has a vtable and
12238  * returns TRUE on success.  On error returns FALSE and sets @error.
12239  */
12240 static gboolean
12241 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12242 {
12243         MonoClass *gklass = klass->generic_class->container_class;
12244
12245         mono_error_init (error);
12246
12247         if (!ensure_runtime_vtable (gklass, error))
12248                 return FALSE;
12249
12250         fix_partial_generic_class (klass);
12251
12252         return TRUE;
12253 }
12254
12255 /**
12256  * ensure_runtime_vtable:
12257  * @klass the class
12258  * @error set on error
12259  *
12260  * Ensures that @klass has a vtable and returns TRUE on success. On
12261  * error returns FALSE and sets @error.
12262  */
12263 static gboolean
12264 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12265 {
12266         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12267         int i, num, j;
12268
12269         mono_error_init (error);
12270
12271         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12272                 return TRUE;
12273         if (klass->parent)
12274                 if (!ensure_runtime_vtable (klass->parent, error))
12275                         return FALSE;
12276
12277         if (tb) {
12278                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12279                 num += tb->num_methods;
12280                 klass->method.count = num;
12281                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12282                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12283                 for (i = 0; i < num; ++i) {
12284                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12285                         if (!ctor)
12286                                 return FALSE;
12287                         klass->methods [i] = ctor;
12288                 }
12289                 num = tb->num_methods;
12290                 j = i;
12291                 for (i = 0; i < num; ++i) {
12292                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12293                         if (!meth)
12294                                 return FALSE;
12295                         klass->methods [j++] = meth;
12296                 }
12297         
12298                 if (tb->interfaces) {
12299                         klass->interface_count = mono_array_length (tb->interfaces);
12300                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12301                         for (i = 0; i < klass->interface_count; ++i) {
12302                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12303                                 return_val_if_nok (error, FALSE);
12304                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12305                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12306                                         return FALSE;
12307                         }
12308                         klass->interfaces_inited = 1;
12309                 }
12310         } else if (klass->generic_class){
12311                 if (!ensure_generic_class_runtime_vtable (klass, error))
12312                         return FALSE;
12313         }
12314
12315         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12316                 int slot_num = 0;
12317                 for (i = 0; i < klass->method.count; ++i) {
12318                         MonoMethod *im = klass->methods [i];
12319                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12320                                 im->slot = slot_num++;
12321                 }
12322                 
12323                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12324                 mono_class_setup_interface_offsets (klass);
12325                 mono_class_setup_interface_id (klass);
12326         }
12327
12328         /*
12329          * The generic vtable is needed even if image->run is not set since some
12330          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12331          * method->slot being defined.
12332          */
12333
12334         /* 
12335          * tb->methods could not be freed since it is used for determining 
12336          * overrides during dynamic vtable construction.
12337          */
12338
12339         return TRUE;
12340 }
12341
12342 static MonoMethod*
12343 mono_reflection_method_get_handle (MonoObject *method)
12344 {
12345         MonoError error;
12346         MonoClass *klass = mono_object_class (method);
12347         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12348                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12349                 return sr_method->method;
12350         }
12351         if (is_sre_method_builder (klass)) {
12352                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12353                 return mb->mhandle;
12354         }
12355         if (is_sre_method_on_tb_inst (klass)) {
12356                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12357                 MonoMethod *result;
12358                 /*FIXME move this to a proper method and unify with resolve_object*/
12359                 if (m->method_args) {
12360                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12361                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12362                 } else {
12363                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12364                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12365                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12366                         MonoMethod *mono_method;
12367
12368                         if (is_sre_method_builder (mono_object_class (m->mb)))
12369                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12370                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12371                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12372                         else
12373                                 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)));
12374
12375                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12376                 }
12377                 return result;
12378         }
12379
12380         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12381         return NULL;
12382 }
12383
12384 void
12385 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12386 {
12387         MonoReflectionTypeBuilder *tb;
12388         int i, j, onum;
12389         MonoReflectionMethod *m;
12390
12391         *overrides = NULL;
12392         *num_overrides = 0;
12393
12394         g_assert (image_is_dynamic (klass->image));
12395
12396         if (!mono_class_get_ref_info (klass))
12397                 return;
12398
12399         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12400
12401         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12402
12403         onum = 0;
12404         if (tb->methods) {
12405                 for (i = 0; i < tb->num_methods; ++i) {
12406                         MonoReflectionMethodBuilder *mb = 
12407                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12408                         if (mb->override_methods)
12409                                 onum += mono_array_length (mb->override_methods);
12410                 }
12411         }
12412
12413         if (onum) {
12414                 *overrides = g_new0 (MonoMethod*, onum * 2);
12415
12416                 onum = 0;
12417                 for (i = 0; i < tb->num_methods; ++i) {
12418                         MonoReflectionMethodBuilder *mb = 
12419                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12420                         if (mb->override_methods) {
12421                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12422                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12423
12424                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12425                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12426
12427                                         g_assert (mb->mhandle);
12428
12429                                         onum ++;
12430                                 }
12431                         }
12432                 }
12433         }
12434
12435         *num_overrides = onum;
12436 }
12437
12438 static void
12439 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12440 {
12441         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12442         MonoReflectionFieldBuilder *fb;
12443         MonoClassField *field;
12444         MonoImage *image = klass->image;
12445         const char *p, *p2;
12446         int i;
12447         guint32 len, idx, real_size = 0;
12448
12449         klass->field.count = tb->num_fields;
12450         klass->field.first = 0;
12451
12452         mono_error_init (error);
12453
12454         if (tb->class_size) {
12455                 if ((tb->packing_size & 0xffffff00) != 0) {
12456                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12457                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12458                         return;
12459                 }
12460                 klass->packing_size = tb->packing_size;
12461                 real_size = klass->instance_size + tb->class_size;
12462         }
12463
12464         if (!klass->field.count) {
12465                 klass->instance_size = MAX (klass->instance_size, real_size);
12466                 return;
12467         }
12468         
12469         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12470         mono_class_alloc_ext (klass);
12471         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12472         /*
12473         This is, guess what, a hack.
12474         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12475         On the static path no field class is resolved, only types are built. This is the right thing to do
12476         but we suck.
12477         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12478         */
12479         klass->size_inited = 1;
12480
12481         for (i = 0; i < klass->field.count; ++i) {
12482                 MonoArray *rva_data;
12483                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12484                 field = &klass->fields [i];
12485                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12486                 if (!mono_error_ok (error))
12487                         return;
12488                 if (fb->attrs) {
12489                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12490                         return_if_nok (error);
12491                         field->type = mono_metadata_type_dup (klass->image, type);
12492                         field->type->attrs = fb->attrs;
12493                 } else {
12494                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12495                         return_if_nok (error);
12496                 }
12497
12498                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12499                         char *base = mono_array_addr (rva_data, char, 0);
12500                         size_t size = mono_array_length (rva_data);
12501                         char *data = (char *)mono_image_alloc (klass->image, size);
12502                         memcpy (data, base, size);
12503                         klass->ext->field_def_values [i].data = data;
12504                 }
12505                 if (fb->offset != -1)
12506                         field->offset = fb->offset;
12507                 field->parent = klass;
12508                 fb->handle = field;
12509                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12510
12511                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12512                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12513                 }
12514                 if (fb->def_value) {
12515                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12516                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12517                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12518                         /* Copy the data from the blob since it might get realloc-ed */
12519                         p = assembly->blob.data + idx;
12520                         len = mono_metadata_decode_blob_size (p, &p2);
12521                         len += p2 - p;
12522                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12523                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12524                 }
12525         }
12526
12527         klass->instance_size = MAX (klass->instance_size, real_size);
12528         mono_class_layout_fields (klass);
12529 }
12530
12531 static void
12532 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12533 {
12534         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12535         MonoReflectionPropertyBuilder *pb;
12536         MonoImage *image = klass->image;
12537         MonoProperty *properties;
12538         int i;
12539
12540         mono_error_init (error);
12541
12542         if (!klass->ext)
12543                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12544
12545         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12546         klass->ext->property.first = 0;
12547
12548         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12549         klass->ext->properties = properties;
12550         for (i = 0; i < klass->ext->property.count; ++i) {
12551                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12552                 properties [i].parent = klass;
12553                 properties [i].attrs = pb->attrs;
12554                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12555                 if (!mono_error_ok (error))
12556                         return;
12557                 if (pb->get_method)
12558                         properties [i].get = pb->get_method->mhandle;
12559                 if (pb->set_method)
12560                         properties [i].set = pb->set_method->mhandle;
12561
12562                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12563                 if (pb->def_value) {
12564                         guint32 len, idx;
12565                         const char *p, *p2;
12566                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12567                         if (!klass->ext->prop_def_values)
12568                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12569                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12570                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12571                         /* Copy the data from the blob since it might get realloc-ed */
12572                         p = assembly->blob.data + idx;
12573                         len = mono_metadata_decode_blob_size (p, &p2);
12574                         len += p2 - p;
12575                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12576                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12577                 }
12578         }
12579 }
12580
12581 MonoReflectionEvent *
12582 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12583 {
12584         MonoError error;
12585         MonoEvent *event = g_new0 (MonoEvent, 1);
12586         MonoClass *klass;
12587
12588         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12589         mono_error_raise_exception (&error); /* FIXME don't raise here */
12590         klass = mono_class_from_mono_type (type);
12591
12592         event->parent = klass;
12593         event->attrs = eb->attrs;
12594         event->name = mono_string_to_utf8 (eb->name);
12595         if (eb->add_method)
12596                 event->add = eb->add_method->mhandle;
12597         if (eb->remove_method)
12598                 event->remove = eb->remove_method->mhandle;
12599         if (eb->raise_method)
12600                 event->raise = eb->raise_method->mhandle;
12601
12602 #ifndef MONO_SMALL_CONFIG
12603         if (eb->other_methods) {
12604                 int j;
12605                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12606                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12607                         MonoReflectionMethodBuilder *mb = 
12608                                 mono_array_get (eb->other_methods,
12609                                                 MonoReflectionMethodBuilder*, j);
12610                         event->other [j] = mb->mhandle;
12611                 }
12612         }
12613 #endif
12614
12615         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12616         mono_error_raise_exception (&error); /* FIXME don't raise here */
12617         return ev_obj;
12618 }
12619
12620 static void
12621 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12622 {
12623         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12624         MonoReflectionEventBuilder *eb;
12625         MonoImage *image = klass->image;
12626         MonoEvent *events;
12627         int i;
12628
12629         mono_error_init (error);
12630
12631         if (!klass->ext)
12632                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12633
12634         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12635         klass->ext->event.first = 0;
12636
12637         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12638         klass->ext->events = events;
12639         for (i = 0; i < klass->ext->event.count; ++i) {
12640                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12641                 events [i].parent = klass;
12642                 events [i].attrs = eb->attrs;
12643                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12644                 if (!mono_error_ok (error))
12645                         return;
12646                 if (eb->add_method)
12647                         events [i].add = eb->add_method->mhandle;
12648                 if (eb->remove_method)
12649                         events [i].remove = eb->remove_method->mhandle;
12650                 if (eb->raise_method)
12651                         events [i].raise = eb->raise_method->mhandle;
12652
12653 #ifndef MONO_SMALL_CONFIG
12654                 if (eb->other_methods) {
12655                         int j;
12656                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12657                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12658                                 MonoReflectionMethodBuilder *mb = 
12659                                         mono_array_get (eb->other_methods,
12660                                                                         MonoReflectionMethodBuilder*, j);
12661                                 events [i].other [j] = mb->mhandle;
12662                         }
12663                 }
12664 #endif
12665                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12666         }
12667 }
12668
12669 static gboolean
12670 remove_instantiations_of_and_ensure_contents (gpointer key,
12671                                                   gpointer value,
12672                                                   gpointer user_data)
12673 {
12674         MonoType *type = (MonoType*)key;
12675         MonoClass *klass = (MonoClass*)user_data;
12676
12677         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12678                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12679                 return TRUE;
12680         } else
12681                 return FALSE;
12682 }
12683
12684 static void
12685 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12686 {
12687         mono_error_init (error);
12688         int i;
12689
12690         if (!arr)
12691                 return;
12692
12693         for (i = 0; i < mono_array_length (arr); ++i) {
12694                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12695                 if (!mono_error_ok (error))
12696                         break;
12697         }
12698 }
12699
12700 MonoReflectionType*
12701 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12702 {
12703         MonoError error;
12704         MonoClass *klass;
12705         MonoDomain* domain;
12706         MonoReflectionType* res;
12707         int i, j;
12708
12709         domain = mono_object_domain (tb);
12710         klass = mono_class_from_mono_type (tb->type.type);
12711
12712         /*
12713          * Check for user defined Type subclasses.
12714          */
12715         RESOLVE_TYPE (tb->parent, &error);
12716         mono_error_raise_exception (&error); /* FIXME don't raise here */
12717         check_array_for_usertypes (tb->interfaces, &error);
12718         mono_error_raise_exception (&error); /*FIXME don't raise here */
12719         if (tb->fields) {
12720                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12721                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12722                         if (fb) {
12723                                 RESOLVE_TYPE (fb->type, &error);
12724                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12725                                 check_array_for_usertypes (fb->modreq, &error);
12726                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12727                                 check_array_for_usertypes (fb->modopt, &error);
12728                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12729                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12730                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12731                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12732                                 }
12733                         }
12734                 }
12735         }
12736         if (tb->methods) {
12737                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12738                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12739                         if (mb) {
12740                                 RESOLVE_TYPE (mb->rtype, &error);
12741                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12742                                 check_array_for_usertypes (mb->return_modreq, &error);
12743                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12744                                 check_array_for_usertypes (mb->return_modopt, &error);
12745                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12746                                 check_array_for_usertypes (mb->parameters, &error);
12747                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12748                                 if (mb->param_modreq)
12749                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12750                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12751                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12752                                         }
12753                                 if (mb->param_modopt)
12754                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12755                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12756                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12757                                         }
12758                         }
12759                 }
12760         }
12761         if (tb->ctors) {
12762                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12763                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12764                         if (mb) {
12765                                 check_array_for_usertypes (mb->parameters, &error);
12766                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12767                                 if (mb->param_modreq)
12768                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12769                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12770                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12771                                         }
12772                                 if (mb->param_modopt)
12773                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12774                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12775                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12776                                         }
12777                         }
12778                 }
12779         }
12780
12781         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12782
12783         /* 
12784          * we need to lock the domain because the lock will be taken inside
12785          * So, we need to keep the locking order correct.
12786          */
12787         mono_loader_lock ();
12788         mono_domain_lock (domain);
12789         if (klass->wastypebuilder) {
12790                 mono_domain_unlock (domain);
12791                 mono_loader_unlock ();
12792
12793                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12794                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12795
12796                 return res;
12797         }
12798         /*
12799          * Fields to set in klass:
12800          * the various flags: delegate/unicode/contextbound etc.
12801          */
12802         klass->flags = tb->attrs;
12803         klass->has_cctor = 1;
12804         klass->has_finalize = 1;
12805         klass->has_finalize_inited = 1;
12806
12807         mono_class_setup_parent (klass, klass->parent);
12808         /* fool mono_class_setup_supertypes */
12809         klass->supertypes = NULL;
12810         mono_class_setup_supertypes (klass);
12811         mono_class_setup_mono_type (klass);
12812
12813 #if 0
12814         if (!((MonoDynamicImage*)klass->image)->run) {
12815                 if (klass->generic_container) {
12816                         /* FIXME: The code below can't handle generic classes */
12817                         klass->wastypebuilder = TRUE;
12818                         mono_loader_unlock ();
12819                         mono_domain_unlock (domain);
12820
12821                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12822                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12823
12824                         return res;
12825                 }
12826         }
12827 #endif
12828
12829         /* enums are done right away */
12830         if (!klass->enumtype)
12831                 if (!ensure_runtime_vtable (klass, &error))
12832                         goto failure;
12833
12834         if (tb->subtypes) {
12835                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12836                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12837                         mono_class_alloc_ext (klass);
12838                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12839                         if (!is_ok (&error)) goto failure;
12840                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12841                 }
12842         }
12843
12844         klass->nested_classes_inited = TRUE;
12845
12846         /* fields and object layout */
12847         if (klass->parent) {
12848                 if (!klass->parent->size_inited)
12849                         mono_class_init (klass->parent);
12850                 klass->instance_size = klass->parent->instance_size;
12851                 klass->sizes.class_size = 0;
12852                 klass->min_align = klass->parent->min_align;
12853                 /* if the type has no fields we won't call the field_setup
12854                  * routine which sets up klass->has_references.
12855                  */
12856                 klass->has_references |= klass->parent->has_references;
12857         } else {
12858                 klass->instance_size = sizeof (MonoObject);
12859                 klass->min_align = 1;
12860         }
12861
12862         /* FIXME: handle packing_size and instance_size */
12863         typebuilder_setup_fields (klass, &error);
12864         if (!mono_error_ok (&error))
12865                 goto failure;
12866         typebuilder_setup_properties (klass, &error);
12867         if (!mono_error_ok (&error))
12868                 goto failure;
12869
12870         typebuilder_setup_events (klass, &error);
12871         if (!mono_error_ok (&error))
12872                 goto failure;
12873
12874         klass->wastypebuilder = TRUE;
12875
12876         /* 
12877          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12878          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12879          * we want to return normal System.MonoType objects, so clear these out from the cache.
12880          *
12881          * Together with this we must ensure the contents of all instances to match the created type.
12882          */
12883         if (domain->type_hash && klass->generic_container)
12884                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12885
12886         mono_domain_unlock (domain);
12887         mono_loader_unlock ();
12888
12889         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12890                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12891                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12892         }
12893
12894         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12895         mono_error_raise_exception (&error); /* FIXME don't raise here */
12896
12897         g_assert (res != (MonoReflectionType*)tb);
12898
12899         return res;
12900
12901 failure:
12902         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12903         klass->wastypebuilder = TRUE;
12904         mono_domain_unlock (domain);
12905         mono_loader_unlock ();
12906         mono_error_raise_exception (&error);
12907         return NULL;
12908 }
12909
12910 void
12911 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12912 {
12913         MonoGenericParamFull *param;
12914         MonoImage *image;
12915         MonoClass *pklass;
12916         MonoError error;
12917
12918         image = &gparam->tbuilder->module->dynamic_image->image;
12919
12920         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12921
12922         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12923         g_assert (mono_error_ok (&error));
12924         param->param.num = gparam->index;
12925
12926         if (gparam->mbuilder) {
12927                 if (!gparam->mbuilder->generic_container) {
12928                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
12929                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12930
12931                         MonoClass *klass = mono_class_from_mono_type (tb);
12932                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12933                         gparam->mbuilder->generic_container->is_method = TRUE;
12934                         /* 
12935                          * Cannot set owner.method, since the MonoMethod is not created yet.
12936                          * Set the image field instead, so type_in_image () works.
12937                          */
12938                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12939                         gparam->mbuilder->generic_container->owner.image = klass->image;
12940                 }
12941                 param->param.owner = gparam->mbuilder->generic_container;
12942         } else if (gparam->tbuilder) {
12943                 if (!gparam->tbuilder->generic_container) {
12944                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
12945                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12946                         MonoClass *klass = mono_class_from_mono_type (tb);
12947                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12948                         gparam->tbuilder->generic_container->owner.klass = klass;
12949                 }
12950                 param->param.owner = gparam->tbuilder->generic_container;
12951         }
12952
12953         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12954
12955         gparam->type.type = &pklass->byval_arg;
12956
12957         mono_class_set_ref_info (pklass, gparam);
12958         mono_image_append_class_to_reflection_info_set (pklass);
12959 }
12960
12961 MonoArray *
12962 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12963 {
12964         MonoError error;
12965         MonoReflectionModuleBuilder *module = sig->module;
12966         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12967         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12968         guint32 buflen, i;
12969         MonoArray *result;
12970         SigBuffer buf;
12971
12972         check_array_for_usertypes (sig->arguments, &error);
12973         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12974
12975         sigbuffer_init (&buf, 32);
12976
12977         sigbuffer_add_value (&buf, 0x07);
12978         sigbuffer_add_value (&buf, na);
12979         if (assembly != NULL){
12980                 for (i = 0; i < na; ++i) {
12981                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12982                         encode_reflection_type (assembly, type, &buf, &error);
12983                         if (!is_ok (&error)) goto fail;
12984                 }
12985         }
12986
12987         buflen = buf.p - buf.buf;
12988         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12989         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12990         sigbuffer_free (&buf);
12991         return result;
12992 fail:
12993         sigbuffer_free (&buf);
12994         mono_error_raise_exception (&error); /* FIXME don't raise here */
12995         return NULL;
12996 }
12997
12998 MonoArray *
12999 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13000 {
13001         MonoError error;
13002         MonoDynamicImage *assembly = sig->module->dynamic_image;
13003         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13004         guint32 buflen, i;
13005         MonoArray *result;
13006         SigBuffer buf;
13007
13008         check_array_for_usertypes (sig->arguments, &error);
13009         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13010
13011         sigbuffer_init (&buf, 32);
13012
13013         sigbuffer_add_value (&buf, 0x06);
13014         for (i = 0; i < na; ++i) {
13015                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13016                 encode_reflection_type (assembly, type, &buf, &error);
13017                 if (!is_ok (&error))
13018                         goto fail;
13019         }
13020
13021         buflen = buf.p - buf.buf;
13022         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13023         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13024         sigbuffer_free (&buf);
13025
13026         return result;
13027 fail:
13028         sigbuffer_free (&buf);
13029         mono_error_raise_exception (&error); /* FIXME don't raise here */
13030         return NULL;
13031 }
13032
13033 typedef struct {
13034         MonoMethod *handle;
13035         MonoDomain *domain;
13036 } DynamicMethodReleaseData;
13037
13038 /*
13039  * The runtime automatically clean up those after finalization.
13040 */      
13041 static MonoReferenceQueue *dynamic_method_queue;
13042
13043 static void
13044 free_dynamic_method (void *dynamic_method)
13045 {
13046         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13047         MonoDomain *domain = data->domain;
13048         MonoMethod *method = data->handle;
13049         guint32 dis_link;
13050
13051         mono_domain_lock (domain);
13052         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13053         g_hash_table_remove (domain->method_to_dyn_method, method);
13054         mono_domain_unlock (domain);
13055         g_assert (dis_link);
13056         mono_gchandle_free (dis_link);
13057
13058         mono_runtime_free_method (domain, method);
13059         g_free (data);
13060 }
13061
13062 void 
13063 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13064 {
13065         MonoError error;
13066         MonoReferenceQueue *queue;
13067         MonoMethod *handle;
13068         DynamicMethodReleaseData *release_data;
13069         ReflectionMethodBuilder rmb;
13070         MonoMethodSignature *sig;
13071         MonoClass *klass;
13072         MonoDomain *domain;
13073         GSList *l;
13074         int i;
13075
13076         if (mono_runtime_is_shutting_down ())
13077                 mono_raise_exception (mono_get_exception_invalid_operation (""));
13078
13079         if (!(queue = dynamic_method_queue)) {
13080                 mono_loader_lock ();
13081                 if (!(queue = dynamic_method_queue))
13082                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13083                 mono_loader_unlock ();
13084         }
13085
13086         sig = dynamic_method_to_signature (mb);
13087
13088         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13089
13090         /*
13091          * Resolve references.
13092          */
13093         /* 
13094          * Every second entry in the refs array is reserved for storing handle_class,
13095          * which is needed by the ldtoken implementation in the JIT.
13096          */
13097         rmb.nrefs = mb->nrefs;
13098         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13099         for (i = 0; i < mb->nrefs; i += 2) {
13100                 MonoClass *handle_class;
13101                 gpointer ref;
13102                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13103
13104                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13105                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13106                         /*
13107                          * The referenced DynamicMethod should already be created by the managed
13108                          * code, except in the case of circular references. In that case, we store
13109                          * method in the refs array, and fix it up later when the referenced 
13110                          * DynamicMethod is created.
13111                          */
13112                         if (method->mhandle) {
13113                                 ref = method->mhandle;
13114                         } else {
13115                                 /* FIXME: GC object stored in unmanaged memory */
13116                                 ref = method;
13117
13118                                 /* FIXME: GC object stored in unmanaged memory */
13119                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13120                         }
13121                         handle_class = mono_defaults.methodhandle_class;
13122                 } else {
13123                         MonoException *ex = NULL;
13124                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13125                         if (!ref)
13126                                 ex = mono_get_exception_type_load (NULL, NULL);
13127                         else if (mono_security_core_clr_enabled ())
13128                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13129
13130                         if (ex) {
13131                                 g_free (rmb.refs);
13132                                 mono_raise_exception (ex);
13133                                 return;
13134                         }
13135                 }
13136
13137                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13138                 rmb.refs [i + 1] = handle_class;
13139         }               
13140
13141         if (mb->owner) {
13142                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13143                 if (!is_ok (&error)) {
13144                         g_free (rmb.refs);
13145                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13146                 }
13147                 klass = mono_class_from_mono_type (owner_type);
13148         } else {
13149                 klass = mono_defaults.object_class;
13150         }
13151
13152         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13153         release_data = g_new (DynamicMethodReleaseData, 1);
13154         release_data->handle = handle;
13155         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13156         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13157                 g_free (release_data);
13158
13159         /* Fix up refs entries pointing at us */
13160         for (l = mb->referenced_by; l; l = l->next) {
13161                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13162                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13163                 gpointer *data;
13164                 
13165                 g_assert (method->mhandle);
13166
13167                 data = (gpointer*)wrapper->method_data;
13168                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13169                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13170                                 data [i + 1] = mb->mhandle;
13171                 }
13172         }
13173         g_slist_free (mb->referenced_by);
13174
13175         g_free (rmb.refs);
13176
13177         /* ilgen is no longer needed */
13178         mb->ilgen = NULL;
13179
13180         domain = mono_domain_get ();
13181         mono_domain_lock (domain);
13182         if (!domain->method_to_dyn_method)
13183                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13184         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13185         mono_domain_unlock (domain);
13186 }
13187
13188 #endif /* DISABLE_REFLECTION_EMIT */
13189
13190 /**
13191  * 
13192  * mono_reflection_is_valid_dynamic_token:
13193  * 
13194  * Returns TRUE if token is valid.
13195  * 
13196  */
13197 gboolean
13198 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13199 {
13200         return lookup_dyn_token (image, token) != NULL;
13201 }
13202
13203 MonoMethodSignature *
13204 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13205 {
13206         MonoMethodSignature *sig;
13207         g_assert (image_is_dynamic (image));
13208
13209         mono_error_init (error);
13210
13211         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13212         if (sig)
13213                 return sig;
13214
13215         return mono_method_signature_checked (method, error);
13216 }
13217
13218 #ifndef DISABLE_REFLECTION_EMIT
13219
13220 /**
13221  * mono_reflection_lookup_dynamic_token:
13222  *
13223  * Finish the Builder object pointed to by TOKEN and return the corresponding
13224  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13225  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13226  * mapping table.
13227  *
13228  * LOCKING: Take the loader lock
13229  */
13230 gpointer
13231 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13232 {
13233         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13234         MonoObject *obj;
13235         MonoClass *klass;
13236
13237         obj = lookup_dyn_token (assembly, token);
13238         if (!obj) {
13239                 if (valid_token)
13240                         g_error ("Could not find required dynamic token 0x%08x", token);
13241                 else
13242                         return NULL;
13243         }
13244
13245         if (!handle_class)
13246                 handle_class = &klass;
13247         return resolve_object (image, obj, handle_class, context);
13248 }
13249
13250 /*
13251  * ensure_complete_type:
13252  *
13253  *   Ensure that KLASS is completed if it is a dynamic type, or references
13254  * dynamic types.
13255  */
13256 static void
13257 ensure_complete_type (MonoClass *klass)
13258 {
13259         MonoError error;
13260
13261         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13262                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13263
13264                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13265                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13266
13267                 // Asserting here could break a lot of code
13268                 //g_assert (klass->wastypebuilder);
13269         }
13270
13271         if (klass->generic_class) {
13272                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13273                 int i;
13274
13275                 for (i = 0; i < inst->type_argc; ++i) {
13276                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13277                 }
13278         }
13279 }
13280
13281 static gpointer
13282 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13283 {
13284         MonoError error;
13285         gpointer result = NULL;
13286
13287         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13288                 result = mono_string_intern_checked ((MonoString*)obj, &error);
13289                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13290                 *handle_class = mono_defaults.string_class;
13291                 g_assert (result);
13292         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13293                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13294                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13295                 MonoClass *mc = mono_class_from_mono_type (type);
13296                 if (!mono_class_init (mc))
13297                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
13298
13299                 if (context) {
13300                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13301                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13302
13303                         result = mono_class_from_mono_type (inflated);
13304                         mono_metadata_free_type (inflated);
13305                 } else {
13306                         result = mono_class_from_mono_type (type);
13307                 }
13308                 *handle_class = mono_defaults.typehandle_class;
13309                 g_assert (result);
13310         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13311                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13312                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13313                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13314                 result = ((MonoReflectionMethod*)obj)->method;
13315                 if (context) {
13316                         MonoError error;
13317                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13318                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13319                 }
13320                 *handle_class = mono_defaults.methodhandle_class;
13321                 g_assert (result);
13322         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13323                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13324                 result = mb->mhandle;
13325                 if (!result) {
13326                         /* Type is not yet created */
13327                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13328
13329                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13330                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13331
13332                         /*
13333                          * Hopefully this has been filled in by calling CreateType() on the
13334                          * TypeBuilder.
13335                          */
13336                         /*
13337                          * TODO: This won't work if the application finishes another 
13338                          * TypeBuilder instance instead of this one.
13339                          */
13340                         result = mb->mhandle;
13341                 }
13342                 if (context) {
13343                         MonoError error;
13344                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13345                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13346                 }
13347                 *handle_class = mono_defaults.methodhandle_class;
13348         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13349                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13350
13351                 result = cb->mhandle;
13352                 if (!result) {
13353                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13354
13355                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13356                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13357                         result = cb->mhandle;
13358                 }
13359                 if (context) {
13360                         MonoError error;
13361                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13362                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13363                 }
13364                 *handle_class = mono_defaults.methodhandle_class;
13365         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13366                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13367
13368                 ensure_complete_type (field->parent);
13369                 if (context) {
13370                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13371                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13372
13373                         MonoClass *klass = mono_class_from_mono_type (inflated);
13374                         MonoClassField *inflated_field;
13375                         gpointer iter = NULL;
13376                         mono_metadata_free_type (inflated);
13377                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13378                                 if (!strcmp (field->name, inflated_field->name))
13379                                         break;
13380                         }
13381                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13382                         result = inflated_field;
13383                 } else {
13384                         result = field;
13385                 }
13386                 *handle_class = mono_defaults.fieldhandle_class;
13387                 g_assert (result);
13388         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13389                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13390                 result = fb->handle;
13391
13392                 if (!result) {
13393                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13394
13395                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13396                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13397                         result = fb->handle;
13398                 }
13399
13400                 if (fb->handle && fb->handle->parent->generic_container) {
13401                         MonoClass *klass = fb->handle->parent;
13402                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13403                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13404
13405                         MonoClass *inflated = mono_class_from_mono_type (type);
13406
13407                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13408                         g_assert (result);
13409                         mono_metadata_free_type (type);
13410                 }
13411                 *handle_class = mono_defaults.fieldhandle_class;
13412         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13413                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13414                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13415                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13416                 MonoClass *klass;
13417
13418                 klass = type->data.klass;
13419                 if (klass->wastypebuilder) {
13420                         /* Already created */
13421                         result = klass;
13422                 }
13423                 else {
13424                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13425                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13426                         result = type->data.klass;
13427                         g_assert (result);
13428                 }
13429                 *handle_class = mono_defaults.typehandle_class;
13430         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13431                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13432                 MonoMethodSignature *sig;
13433                 int nargs, i;
13434
13435                 if (helper->arguments)
13436                         nargs = mono_array_length (helper->arguments);
13437                 else
13438                         nargs = 0;
13439
13440                 sig = mono_metadata_signature_alloc (image, nargs);
13441                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13442                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13443
13444                 if (helper->unmanaged_call_conv) { /* unmanaged */
13445                         sig->call_convention = helper->unmanaged_call_conv - 1;
13446                         sig->pinvoke = TRUE;
13447                 } else if (helper->call_conv & 0x02) {
13448                         sig->call_convention = MONO_CALL_VARARG;
13449                 } else {
13450                         sig->call_convention = MONO_CALL_DEFAULT;
13451                 }
13452
13453                 sig->param_count = nargs;
13454                 /* TODO: Copy type ? */
13455                 sig->ret = helper->return_type->type;
13456                 for (i = 0; i < nargs; ++i) {
13457                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13458                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13459                 }
13460
13461                 result = sig;
13462                 *handle_class = NULL;
13463         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13464                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13465                 /* Already created by the managed code */
13466                 g_assert (method->mhandle);
13467                 result = method->mhandle;
13468                 *handle_class = mono_defaults.methodhandle_class;
13469         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13470                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13471                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13472                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13473                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13474
13475                 result = mono_class_from_mono_type (type);
13476                 *handle_class = mono_defaults.typehandle_class;
13477                 g_assert (result);
13478                 mono_metadata_free_type (type);
13479         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13480                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13481                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13482                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13483                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13484
13485                 result = mono_class_from_mono_type (type);
13486                 *handle_class = mono_defaults.typehandle_class;
13487                 g_assert (result);
13488                 mono_metadata_free_type (type);
13489         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13490                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13491                 MonoClass *inflated;
13492                 MonoType *type;
13493                 MonoClassField *field;
13494
13495                 if (is_sre_field_builder (mono_object_class (f->fb)))
13496                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13497                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13498                         field = ((MonoReflectionField*)f->fb)->field;
13499                 else
13500                         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)));
13501
13502                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13503                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13504                 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13505                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13506
13507                 inflated = mono_class_from_mono_type (type);
13508
13509                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13510                 ensure_complete_type (field->parent);
13511                 g_assert (result);
13512                 mono_metadata_free_type (type);
13513                 *handle_class = mono_defaults.fieldhandle_class;
13514         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13515                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13516                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13517                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13518                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13519                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13520
13521                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13522                 MonoMethod *method;
13523
13524                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13525                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13526                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13527                         method = ((MonoReflectionMethod *)c->cb)->method;
13528                 else
13529                         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)));
13530
13531                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13532                 *handle_class = mono_defaults.methodhandle_class;
13533                 mono_metadata_free_type (type);
13534         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13535                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13536                 if (m->method_args) {
13537                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13538                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13539                         if (context) {
13540                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13541                                 mono_error_assert_ok (&error);
13542                         }
13543                 } else {
13544                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13545                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13546                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13547                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13548
13549                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
13550                         MonoMethod *method;
13551
13552                         if (is_sre_method_builder (mono_object_class (m->mb)))
13553                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13554                         else if (is_sr_mono_method (mono_object_class (m->mb)))
13555                                 method = ((MonoReflectionMethod *)m->mb)->method;
13556                         else
13557                                 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)));
13558
13559                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13560                         mono_metadata_free_type (type);
13561                 }
13562                 *handle_class = mono_defaults.methodhandle_class;
13563         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13564                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13565                 MonoType *mtype;
13566                 MonoClass *klass;
13567                 MonoMethod *method;
13568                 gpointer iter;
13569                 char *name;
13570
13571                 mtype = mono_reflection_type_get_handle (m->parent, &error);
13572                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13573                 klass = mono_class_from_mono_type (mtype);
13574
13575                 /* Find the method */
13576
13577                 name = mono_string_to_utf8 (m->name);
13578                 iter = NULL;
13579                 while ((method = mono_class_get_methods (klass, &iter))) {
13580                         if (!strcmp (method->name, name))
13581                                 break;
13582                 }
13583                 g_free (name);
13584
13585                 // FIXME:
13586                 g_assert (method);
13587                 // FIXME: Check parameters/return value etc. match
13588
13589                 result = method;
13590                 *handle_class = mono_defaults.methodhandle_class;
13591         } else if (is_sre_array (mono_object_get_class(obj)) ||
13592                                 is_sre_byref (mono_object_get_class(obj)) ||
13593                                 is_sre_pointer (mono_object_get_class(obj))) {
13594                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13595                 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13596                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13597
13598                 if (context) {
13599                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13600                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13601
13602                         result = mono_class_from_mono_type (inflated);
13603                         mono_metadata_free_type (inflated);
13604                 } else {
13605                         result = mono_class_from_mono_type (type);
13606                 }
13607                 *handle_class = mono_defaults.typehandle_class;
13608         } else {
13609                 g_print ("%s\n", obj->vtable->klass->name);
13610                 g_assert_not_reached ();
13611         }
13612         return result;
13613 }
13614
13615 #else /* DISABLE_REFLECTION_EMIT */
13616
13617 MonoArray*
13618 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
13619 {
13620         g_assert_not_reached ();
13621         return NULL;
13622 }
13623
13624 void
13625 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13626 {
13627         g_assert_not_reached ();
13628 }
13629
13630 void
13631 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13632 {
13633         g_assert_not_reached ();
13634 }
13635
13636 void
13637 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13638 {
13639         g_assert_not_reached ();
13640 }
13641
13642 void
13643 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13644 {
13645         g_assert_not_reached ();
13646 }
13647
13648 void
13649 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13650 {
13651         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13652 }
13653
13654 void
13655 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13656 {
13657         g_assert_not_reached ();
13658 }
13659
13660 void
13661 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13662 {
13663         g_assert_not_reached ();
13664 }
13665
13666 MonoReflectionModule *
13667 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13668 {
13669         g_assert_not_reached ();
13670         return NULL;
13671 }
13672
13673 guint32
13674 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13675 {
13676         g_assert_not_reached ();
13677         return 0;
13678 }
13679
13680 guint32
13681 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13682 {
13683         g_assert_not_reached ();
13684         return 0;
13685 }
13686
13687 guint32
13688 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
13689                          gboolean create_open_instance, gboolean register_token, MonoError *error)
13690 {
13691         g_assert_not_reached ();
13692         return 0;
13693 }
13694
13695 void
13696 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13697 {
13698 }
13699
13700 void
13701 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13702 {
13703         g_assert_not_reached ();
13704 }
13705
13706 void
13707 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13708 {
13709         *overrides = NULL;
13710         *num_overrides = 0;
13711 }
13712
13713 MonoReflectionEvent *
13714 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13715 {
13716         g_assert_not_reached ();
13717         return NULL;
13718 }
13719
13720 MonoReflectionType*
13721 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13722 {
13723         g_assert_not_reached ();
13724         return NULL;
13725 }
13726
13727 void
13728 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13729 {
13730         g_assert_not_reached ();
13731 }
13732
13733 MonoArray *
13734 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13735 {
13736         g_assert_not_reached ();
13737         return NULL;
13738 }
13739
13740 MonoArray *
13741 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13742 {
13743         g_assert_not_reached ();
13744         return NULL;
13745 }
13746
13747 void 
13748 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13749 {
13750 }
13751
13752 gpointer
13753 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13754 {
13755         return NULL;
13756 }
13757
13758 MonoType*
13759 mono_reflection_type_get_handle (MonoReflectionType* ref)
13760 {
13761         if (!ref)
13762                 return NULL;
13763         return ref->type;
13764 }
13765
13766 void
13767 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13768 {
13769         g_assert_not_reached ();
13770 }
13771
13772 #endif /* DISABLE_REFLECTION_EMIT */
13773
13774 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13775 const static guint32 declsec_flags_map[] = {
13776         0x00000000,                                     /* empty */
13777         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
13778         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
13779         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
13780         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
13781         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
13782         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
13783         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
13784         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
13785         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
13786         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
13787         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
13788         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
13789         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
13790         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
13791         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
13792         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
13793         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
13794         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
13795 };
13796
13797 /*
13798  * Returns flags that includes all available security action associated to the handle.
13799  * @token: metadata token (either for a class or a method)
13800  * @image: image where resides the metadata.
13801  */
13802 static guint32
13803 mono_declsec_get_flags (MonoImage *image, guint32 token)
13804 {
13805         int index = mono_metadata_declsec_from_index (image, token);
13806         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13807         guint32 result = 0;
13808         guint32 action;
13809         int i;
13810
13811         /* HasSecurity can be present for other, not specially encoded, attributes,
13812            e.g. SuppressUnmanagedCodeSecurityAttribute */
13813         if (index < 0)
13814                 return 0;
13815
13816         for (i = index; i < t->rows; i++) {
13817                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13818
13819                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13820                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13821                         break;
13822
13823                 action = cols [MONO_DECL_SECURITY_ACTION];
13824                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13825                         result |= declsec_flags_map [action];
13826                 } else {
13827                         g_assert_not_reached ();
13828                 }
13829         }
13830         return result;
13831 }
13832
13833 /*
13834  * Get the security actions (in the form of flags) associated with the specified method.
13835  *
13836  * @method: The method for which we want the declarative security flags.
13837  * Return the declarative security flags for the method (only).
13838  *
13839  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13840  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13841  */
13842 guint32
13843 mono_declsec_flags_from_method (MonoMethod *method)
13844 {
13845         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13846                 /* FIXME: No cache (for the moment) */
13847                 guint32 idx = mono_method_get_index (method);
13848                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13849                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13850                 return mono_declsec_get_flags (method->klass->image, idx);
13851         }
13852         return 0;
13853 }
13854
13855 /*
13856  * Get the security actions (in the form of flags) associated with the specified class.
13857  *
13858  * @klass: The class for which we want the declarative security flags.
13859  * Return the declarative security flags for the class.
13860  *
13861  * Note: We cache the flags inside the MonoClass structure as this will get 
13862  *       called very often (at least for each method).
13863  */
13864 guint32
13865 mono_declsec_flags_from_class (MonoClass *klass)
13866 {
13867         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13868                 if (!klass->ext || !klass->ext->declsec_flags) {
13869                         guint32 idx;
13870
13871                         idx = mono_metadata_token_index (klass->type_token);
13872                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13873                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13874                         mono_loader_lock ();
13875                         mono_class_alloc_ext (klass);
13876                         mono_loader_unlock ();
13877                         /* we cache the flags on classes */
13878                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13879                 }
13880                 return klass->ext->declsec_flags;
13881         }
13882         return 0;
13883 }
13884
13885 /*
13886  * Get the security actions (in the form of flags) associated with the specified assembly.
13887  *
13888  * @assembly: The assembly for which we want the declarative security flags.
13889  * Return the declarative security flags for the assembly.
13890  */
13891 guint32
13892 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13893 {
13894         guint32 idx = 1; /* there is only one assembly */
13895         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13896         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13897         return mono_declsec_get_flags (assembly->image, idx);
13898 }
13899
13900
13901 /*
13902  * Fill actions for the specific index (which may either be an encoded class token or
13903  * an encoded method token) from the metadata image.
13904  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13905  */
13906 static MonoBoolean
13907 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13908         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13909 {
13910         MonoBoolean result = FALSE;
13911         MonoTableInfo *t;
13912         guint32 cols [MONO_DECL_SECURITY_SIZE];
13913         int index = mono_metadata_declsec_from_index (image, token);
13914         int i;
13915
13916         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13917         for (i = index; i < t->rows; i++) {
13918                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13919
13920                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13921                         return result;
13922
13923                 /* if present only replace (class) permissions with method permissions */
13924                 /* if empty accept either class or method permissions */
13925                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13926                         if (!actions->demand.blob) {
13927                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13928                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13929                                 actions->demand.blob = (char*) (blob + 2);
13930                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13931                                 result = TRUE;
13932                         }
13933                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13934                         if (!actions->noncasdemand.blob) {
13935                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13936                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13937                                 actions->noncasdemand.blob = (char*) (blob + 2);
13938                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13939                                 result = TRUE;
13940                         }
13941                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13942                         if (!actions->demandchoice.blob) {
13943                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13944                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13945                                 actions->demandchoice.blob = (char*) (blob + 2);
13946                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13947                                 result = TRUE;
13948                         }
13949                 }
13950         }
13951
13952         return result;
13953 }
13954
13955 static MonoBoolean
13956 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
13957         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13958 {
13959         guint32 idx = mono_metadata_token_index (klass->type_token);
13960         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13961         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13962         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13963 }
13964
13965 static MonoBoolean
13966 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
13967         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13968 {
13969         guint32 idx = mono_method_get_index (method);
13970         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13971         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13972         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13973 }
13974
13975 /*
13976  * Collect all actions (that requires to generate code in mini) assigned for
13977  * the specified method.
13978  * Note: Don't use the content of actions if the function return FALSE.
13979  */
13980 MonoBoolean
13981 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13982 {
13983         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
13984                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13985         MonoBoolean result = FALSE;
13986         guint32 flags;
13987
13988         /* quick exit if no declarative security is present in the metadata */
13989         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13990                 return FALSE;
13991
13992         /* we want the original as the wrapper is "free" of the security informations */
13993         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13994                 method = mono_marshal_method_from_wrapper (method);
13995                 if (!method)
13996                         return FALSE;
13997         }
13998
13999         /* First we look for method-level attributes */
14000         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14001                 mono_class_init (method->klass);
14002                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14003
14004                 result = mono_declsec_get_method_demands_params (method, demands, 
14005                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14006         }
14007
14008         /* Here we use (or create) the class declarative cache to look for demands */
14009         flags = mono_declsec_flags_from_class (method->klass);
14010         if (flags & mask) {
14011                 if (!result) {
14012                         mono_class_init (method->klass);
14013                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14014                 }
14015                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14016                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14017         }
14018
14019         /* The boolean return value is used as a shortcut in case nothing needs to
14020            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14021         return result;
14022 }
14023
14024
14025 /*
14026  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14027  *
14028  * Note: Don't use the content of actions if the function return FALSE.
14029  */
14030 MonoBoolean
14031 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14032 {
14033         MonoBoolean result = FALSE;
14034         guint32 flags;
14035
14036         /* quick exit if no declarative security is present in the metadata */
14037         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14038                 return FALSE;
14039
14040         /* we want the original as the wrapper is "free" of the security informations */
14041         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14042                 method = mono_marshal_method_from_wrapper (method);
14043                 if (!method)
14044                         return FALSE;
14045         }
14046
14047         /* results are independant - zeroize both */
14048         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14049         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14050
14051         /* First we look for method-level attributes */
14052         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14053                 mono_class_init (method->klass);
14054
14055                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14056                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14057         }
14058
14059         /* Here we use (or create) the class declarative cache to look for demands */
14060         flags = mono_declsec_flags_from_class (method->klass);
14061         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14062                 mono_class_init (method->klass);
14063
14064                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14065                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14066         }
14067
14068         return result;
14069 }
14070
14071 /*
14072  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14073  *
14074  * @klass       The inherited class - this is the class that provides the security check (attributes)
14075  * @demans      
14076  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14077  * 
14078  * Note: Don't use the content of actions if the function return FALSE.
14079  */
14080 MonoBoolean
14081 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14082 {
14083         MonoBoolean result = FALSE;
14084         guint32 flags;
14085
14086         /* quick exit if no declarative security is present in the metadata */
14087         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14088                 return FALSE;
14089
14090         /* Here we use (or create) the class declarative cache to look for demands */
14091         flags = mono_declsec_flags_from_class (klass);
14092         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14093                 mono_class_init (klass);
14094                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14095
14096                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14097                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14098         }
14099
14100         return result;
14101 }
14102
14103 /*
14104  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14105  *
14106  * Note: Don't use the content of actions if the function return FALSE.
14107  */
14108 MonoBoolean
14109 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14110 {
14111         /* quick exit if no declarative security is present in the metadata */
14112         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14113                 return FALSE;
14114
14115         /* we want the original as the wrapper is "free" of the security informations */
14116         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14117                 method = mono_marshal_method_from_wrapper (method);
14118                 if (!method)
14119                         return FALSE;
14120         }
14121
14122         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14123                 mono_class_init (method->klass);
14124                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14125
14126                 return mono_declsec_get_method_demands_params (method, demands, 
14127                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14128         }
14129         return FALSE;
14130 }
14131
14132
14133 static MonoBoolean
14134 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14135 {
14136         guint32 cols [MONO_DECL_SECURITY_SIZE];
14137         MonoTableInfo *t;
14138         int i;
14139
14140         int index = mono_metadata_declsec_from_index (image, token);
14141         if (index == -1)
14142                 return FALSE;
14143
14144         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14145         for (i = index; i < t->rows; i++) {
14146                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14147
14148                 /* shortcut - index are ordered */
14149                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14150                         return FALSE;
14151
14152                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14153                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14154                         entry->blob = (char*) (metadata + 2);
14155                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14156                         return TRUE;
14157                 }
14158         }
14159
14160         return FALSE;
14161 }
14162
14163 MonoBoolean
14164 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14165 {
14166         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14167                 guint32 idx = mono_method_get_index (method);
14168                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14169                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14170                 return get_declsec_action (method->klass->image, idx, action, entry);
14171         }
14172         return FALSE;
14173 }
14174
14175 MonoBoolean
14176 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14177 {
14178         /* use cache */
14179         guint32 flags = mono_declsec_flags_from_class (klass);
14180         if (declsec_flags_map [action] & flags) {
14181                 guint32 idx = mono_metadata_token_index (klass->type_token);
14182                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14183                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14184                 return get_declsec_action (klass->image, idx, action, entry);
14185         }
14186         return FALSE;
14187 }
14188
14189 MonoBoolean
14190 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14191 {
14192         guint32 idx = 1; /* there is only one assembly */
14193         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14194         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14195
14196         return get_declsec_action (assembly->image, idx, action, entry);
14197 }
14198
14199 gboolean
14200 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14201 {
14202         MonoError error;
14203         MonoObject *res, *exc;
14204         void *params [1];
14205         static MonoMethod *method = NULL;
14206
14207         if (method == NULL) {
14208                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14209                 g_assert (method);
14210         }
14211
14212         /* 
14213          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14214          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14215          */
14216         g_assert (mono_class_get_ref_info (klass));
14217         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14218
14219         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14220         mono_error_raise_exception (&error); /* FIXME don't raise here */
14221
14222         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14223
14224         if (exc || !mono_error_ok (&error)) {
14225                 mono_error_cleanup (&error);
14226                 return FALSE;
14227         } else
14228                 return *(MonoBoolean*)mono_object_unbox (res);
14229 }
14230
14231 /**
14232  * mono_reflection_type_get_type:
14233  * @reftype: the System.Type object
14234  *
14235  * Returns the MonoType* associated with the C# System.Type object @reftype.
14236  */
14237 MonoType*
14238 mono_reflection_type_get_type (MonoReflectionType *reftype)
14239 {
14240         g_assert (reftype);
14241
14242         MonoError error;
14243         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14244         mono_error_assert_ok (&error);
14245         return result;
14246 }
14247
14248 /**
14249  * mono_reflection_assembly_get_assembly:
14250  * @refassembly: the System.Reflection.Assembly object
14251  *
14252  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14253  */
14254 MonoAssembly*
14255 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14256 {
14257         g_assert (refassembly);
14258
14259         return refassembly->assembly;
14260 }
14261