[io-layer] Remove GetCurrentThreadId
[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-internal.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-internal.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);
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);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static void    ensure_runtime_vtable (MonoClass *klass);
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);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
159 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
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);
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);
174 static gboolean is_sre_array (MonoClass *class);
175 static gboolean is_sre_byref (MonoClass *class);
176 static gboolean is_sre_pointer (MonoClass *class);
177 static gboolean is_sre_type_builder (MonoClass *class);
178 static gboolean is_sre_method_builder (MonoClass *class);
179 static gboolean is_sre_ctor_builder (MonoClass *class);
180 static gboolean is_sre_field_builder (MonoClass *class);
181 static gboolean is_sr_mono_method (MonoClass *class);
182 static gboolean is_sr_mono_cmethod (MonoClass *class);
183 static gboolean is_sr_mono_generic_method (MonoClass *class);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
185 static gboolean is_sr_mono_field (MonoClass *class);
186 static gboolean is_sr_mono_property (MonoClass *class);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
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);
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) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
198 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do {   \
199         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index);        \
200         __type = mono_reflection_type_resolve_user_types (__type);      \
201         mono_array_set (arr, MonoReflectionType*, index, __type);       \
202 } while (0)
203
204 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
205
206 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
207 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
208
209 #if SIZEOF_VOID_P == 4
210 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
211 #else
212 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
213 #endif
214
215 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
216 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
217
218
219 void
220 mono_reflection_init (void)
221 {
222 }
223
224 static inline void
225 dynamic_image_lock (MonoDynamicImage *image)
226 {
227         MONO_TRY_BLOCKING;
228         mono_image_lock ((MonoImage*)image);
229         MONO_FINISH_TRY_BLOCKING;
230 }
231
232 static inline void
233 dynamic_image_unlock (MonoDynamicImage *image)
234 {
235         mono_image_unlock ((MonoImage*)image);
236 }
237
238 static void
239 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
240 {
241         MONO_REQ_GC_UNSAFE_MODE;
242
243         dynamic_image_lock (assembly);
244         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
245         dynamic_image_unlock (assembly);
246 }
247
248 static MonoObject*
249 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
250 {
251         MONO_REQ_GC_UNSAFE_MODE;
252
253         MonoObject *obj;
254
255         dynamic_image_lock (assembly);
256         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
257         dynamic_image_unlock (assembly);
258
259         return obj;
260 }
261
262 static void
263 sigbuffer_init (SigBuffer *buf, int size)
264 {
265         MONO_REQ_GC_NEUTRAL_MODE;
266
267         buf->buf = g_malloc (size);
268         buf->p = buf->buf;
269         buf->end = buf->buf + size;
270 }
271
272 static void
273 sigbuffer_make_room (SigBuffer *buf, int size)
274 {
275         MONO_REQ_GC_NEUTRAL_MODE;
276
277         if (buf->end - buf->p < size) {
278                 int new_size = buf->end - buf->buf + size + 32;
279                 char *p = g_realloc (buf->buf, new_size);
280                 size = buf->p - buf->buf;
281                 buf->buf = p;
282                 buf->p = p + size;
283                 buf->end = buf->buf + new_size;
284         }
285 }
286
287 static void
288 sigbuffer_add_value (SigBuffer *buf, guint32 val)
289 {
290         MONO_REQ_GC_NEUTRAL_MODE;
291
292         sigbuffer_make_room (buf, 6);
293         mono_metadata_encode_value (val, buf->p, &buf->p);
294 }
295
296 static void
297 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
298 {
299         MONO_REQ_GC_NEUTRAL_MODE;
300
301         sigbuffer_make_room (buf, 1);
302         buf->p [0] = val;
303         buf->p++;
304 }
305
306 static void
307 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
308 {
309         MONO_REQ_GC_NEUTRAL_MODE;
310
311         sigbuffer_make_room (buf, size);
312         memcpy (buf->p, p, size);
313         buf->p += size;
314 }
315
316 static void
317 sigbuffer_free (SigBuffer *buf)
318 {
319         MONO_REQ_GC_NEUTRAL_MODE;
320
321         g_free (buf->buf);
322 }
323
324 #ifndef DISABLE_REFLECTION_EMIT
325 /**
326  * mp_g_alloc:
327  *
328  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
329  * from the C heap.
330  */
331 static gpointer
332 image_g_malloc (MonoImage *image, guint size)
333 {
334         MONO_REQ_GC_NEUTRAL_MODE;
335
336         if (image)
337                 return mono_image_alloc (image, size);
338         else
339                 return g_malloc (size);
340 }
341 #endif /* !DISABLE_REFLECTION_EMIT */
342
343 /**
344  * image_g_alloc0:
345  *
346  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
347  * from the C heap.
348  */
349 static gpointer
350 image_g_malloc0 (MonoImage *image, guint size)
351 {
352         MONO_REQ_GC_NEUTRAL_MODE;
353
354         if (image)
355                 return mono_image_alloc0 (image, size);
356         else
357                 return g_malloc0 (size);
358 }
359
360 #ifndef DISABLE_REFLECTION_EMIT
361 static char*
362 image_strdup (MonoImage *image, const char *s)
363 {
364         MONO_REQ_GC_NEUTRAL_MODE;
365
366         if (image)
367                 return mono_image_strdup (image, s);
368         else
369                 return g_strdup (s);
370 }
371 #endif
372
373 #define image_g_new(image,struct_type, n_structs)               \
374     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
375
376 #define image_g_new0(image,struct_type, n_structs)              \
377     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
378
379
380 static void
381 alloc_table (MonoDynamicTable *table, guint nrows)
382 {
383         MONO_REQ_GC_NEUTRAL_MODE;
384
385         table->rows = nrows;
386         g_assert (table->columns);
387         if (nrows + 1 >= table->alloc_rows) {
388                 while (nrows + 1 >= table->alloc_rows) {
389                         if (table->alloc_rows == 0)
390                                 table->alloc_rows = 16;
391                         else
392                                 table->alloc_rows *= 2;
393                 }
394
395                 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
396         }
397 }
398
399 static void
400 make_room_in_stream (MonoDynamicStream *stream, int size)
401 {
402         MONO_REQ_GC_NEUTRAL_MODE;
403
404         if (size <= stream->alloc_size)
405                 return;
406         
407         while (stream->alloc_size <= size) {
408                 if (stream->alloc_size < 4096)
409                         stream->alloc_size = 4096;
410                 else
411                         stream->alloc_size *= 2;
412         }
413         
414         stream->data = g_realloc (stream->data, stream->alloc_size);
415 }
416
417 static guint32
418 string_heap_insert (MonoDynamicStream *sh, const char *str)
419 {
420         MONO_REQ_GC_NEUTRAL_MODE;
421
422         guint32 idx;
423         guint32 len;
424         gpointer oldkey, oldval;
425
426         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
427                 return GPOINTER_TO_UINT (oldval);
428
429         len = strlen (str) + 1;
430         idx = sh->index;
431         
432         make_room_in_stream (sh, idx + len);
433
434         /*
435          * We strdup the string even if we already copy them in sh->data
436          * so that the string pointers in the hash remain valid even if
437          * we need to realloc sh->data. We may want to avoid that later.
438          */
439         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
440         memcpy (sh->data + idx, str, len);
441         sh->index += len;
442         return idx;
443 }
444
445 static guint32
446 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
447 {
448         MONO_REQ_GC_UNSAFE_MODE;
449
450         char *name = mono_string_to_utf8 (str);
451         guint32 idx;
452         idx = string_heap_insert (sh, name);
453         g_free (name);
454         return idx;
455 }
456
457 #ifndef DISABLE_REFLECTION_EMIT
458 static void
459 string_heap_init (MonoDynamicStream *sh)
460 {
461         MONO_REQ_GC_NEUTRAL_MODE;
462
463         sh->index = 0;
464         sh->alloc_size = 4096;
465         sh->data = g_malloc (4096);
466         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
467         string_heap_insert (sh, "");
468 }
469 #endif
470
471 static guint32
472 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
473 {
474         MONO_REQ_GC_NEUTRAL_MODE;
475
476         guint32 idx;
477         
478         make_room_in_stream (stream, stream->index + len);
479         memcpy (stream->data + stream->index, data, len);
480         idx = stream->index;
481         stream->index += len;
482         /* 
483          * align index? Not without adding an additional param that controls it since
484          * we may store a blob value in pieces.
485          */
486         return idx;
487 }
488
489 static guint32
490 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
491 {
492         MONO_REQ_GC_NEUTRAL_MODE;
493
494         guint32 idx;
495         
496         make_room_in_stream (stream, stream->index + len);
497         memset (stream->data + stream->index, 0, len);
498         idx = stream->index;
499         stream->index += len;
500         return idx;
501 }
502
503 static void
504 stream_data_align (MonoDynamicStream *stream)
505 {
506         MONO_REQ_GC_NEUTRAL_MODE;
507
508         char buf [4] = {0};
509         guint32 count = stream->index % 4;
510
511         /* we assume the stream data will be aligned */
512         if (count)
513                 mono_image_add_stream_data (stream, buf, 4 - count);
514 }
515
516 #ifndef DISABLE_REFLECTION_EMIT
517 static int
518 mono_blob_entry_hash (const char* str)
519 {
520         MONO_REQ_GC_NEUTRAL_MODE;
521
522         guint len, h;
523         const char *end;
524         len = mono_metadata_decode_blob_size (str, &str);
525         if (len > 0) {
526                 end = str + len;
527                 h = *str;
528                 for (str += 1; str < end; str++)
529                         h = (h << 5) - h + *str;
530                 return h;
531         } else {
532                 return 0;
533         }
534 }
535
536 static gboolean
537 mono_blob_entry_equal (const char *str1, const char *str2) {
538         MONO_REQ_GC_NEUTRAL_MODE;
539
540         int len, len2;
541         const char *end1;
542         const char *end2;
543         len = mono_metadata_decode_blob_size (str1, &end1);
544         len2 = mono_metadata_decode_blob_size (str2, &end2);
545         if (len != len2)
546                 return 0;
547         return memcmp (end1, end2, len) == 0;
548 }
549 #endif
550 static guint32
551 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
552 {
553         MONO_REQ_GC_NEUTRAL_MODE;
554
555         guint32 idx;
556         char *copy;
557         gpointer oldkey, oldval;
558
559         copy = g_malloc (s1+s2);
560         memcpy (copy, b1, s1);
561         memcpy (copy + s1, b2, s2);
562         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
563                 g_free (copy);
564                 idx = GPOINTER_TO_UINT (oldval);
565         } else {
566                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
567                 mono_image_add_stream_data (&assembly->blob, b2, s2);
568                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
569         }
570         return idx;
571 }
572
573 static guint32
574 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
575 {
576         MONO_REQ_GC_NEUTRAL_MODE;
577
578         char blob_size [8];
579         char *b = blob_size;
580         guint32 size = buf->p - buf->buf;
581         /* store length */
582         g_assert (size <= (buf->end - buf->buf));
583         mono_metadata_encode_value (size, b, &b);
584         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
585 }
586
587 /*
588  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
589  * dest may be misaligned.
590  */
591 static void
592 swap_with_size (char *dest, const char* val, int len, int nelem) {
593         MONO_REQ_GC_NEUTRAL_MODE;
594 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
595         int elem;
596
597         for (elem = 0; elem < nelem; ++elem) {
598                 switch (len) {
599                 case 1:
600                         *dest = *val;
601                         break;
602                 case 2:
603                         dest [0] = val [1];
604                         dest [1] = val [0];
605                         break;
606                 case 4:
607                         dest [0] = val [3];
608                         dest [1] = val [2];
609                         dest [2] = val [1];
610                         dest [3] = val [0];
611                         break;
612                 case 8:
613                         dest [0] = val [7];
614                         dest [1] = val [6];
615                         dest [2] = val [5];
616                         dest [3] = val [4];
617                         dest [4] = val [3];
618                         dest [5] = val [2];
619                         dest [6] = val [1];
620                         dest [7] = val [0];
621                         break;
622                 default:
623                         g_assert_not_reached ();
624                 }
625                 dest += len;
626                 val += len;
627         }
628 #else
629         memcpy (dest, val, len * nelem);
630 #endif
631 }
632
633 static guint32
634 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
635 {
636         MONO_REQ_GC_UNSAFE_MODE;
637         
638         char blob_size [64];
639         char *b = blob_size;
640         guint32 idx = 0, len;
641
642         len = str->length * 2;
643         mono_metadata_encode_value (len, b, &b);
644 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
645         {
646                 char *swapped = g_malloc (2 * mono_string_length (str));
647                 const char *p = (const char*)mono_string_chars (str);
648
649                 swap_with_size (swapped, p, 2, mono_string_length (str));
650                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
651                 g_free (swapped);
652         }
653 #else
654         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
655 #endif
656         return idx;
657 }
658
659 #ifndef DISABLE_REFLECTION_EMIT
660 static MonoClass *
661 default_class_from_mono_type (MonoType *type)
662 {
663         MONO_REQ_GC_NEUTRAL_MODE;
664
665         switch (type->type) {
666         case MONO_TYPE_OBJECT:
667                 return mono_defaults.object_class;
668         case MONO_TYPE_VOID:
669                 return mono_defaults.void_class;
670         case MONO_TYPE_BOOLEAN:
671                 return mono_defaults.boolean_class;
672         case MONO_TYPE_CHAR:
673                 return mono_defaults.char_class;
674         case MONO_TYPE_I1:
675                 return mono_defaults.sbyte_class;
676         case MONO_TYPE_U1:
677                 return mono_defaults.byte_class;
678         case MONO_TYPE_I2:
679                 return mono_defaults.int16_class;
680         case MONO_TYPE_U2:
681                 return mono_defaults.uint16_class;
682         case MONO_TYPE_I4:
683                 return mono_defaults.int32_class;
684         case MONO_TYPE_U4:
685                 return mono_defaults.uint32_class;
686         case MONO_TYPE_I:
687                 return mono_defaults.int_class;
688         case MONO_TYPE_U:
689                 return mono_defaults.uint_class;
690         case MONO_TYPE_I8:
691                 return mono_defaults.int64_class;
692         case MONO_TYPE_U8:
693                 return mono_defaults.uint64_class;
694         case MONO_TYPE_R4:
695                 return mono_defaults.single_class;
696         case MONO_TYPE_R8:
697                 return mono_defaults.double_class;
698         case MONO_TYPE_STRING:
699                 return mono_defaults.string_class;
700         default:
701                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
702                 g_assert_not_reached ();
703         }
704         
705         return NULL;
706 }
707 #endif
708
709 /*
710  * mono_class_get_ref_info:
711  *
712  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
713  */
714 gpointer
715 mono_class_get_ref_info (MonoClass *klass)
716 {
717         MONO_REQ_GC_UNSAFE_MODE;
718
719         if (klass->ref_info_handle == 0)
720                 return NULL;
721         else
722                 return mono_gchandle_get_target (klass->ref_info_handle);
723 }
724
725 void
726 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
727 {
728         MONO_REQ_GC_UNSAFE_MODE;
729
730         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
731         g_assert (klass->ref_info_handle != 0);
732 }
733
734 void
735 mono_class_free_ref_info (MonoClass *klass)
736 {
737         MONO_REQ_GC_NEUTRAL_MODE;
738
739         if (klass->ref_info_handle) {
740                 mono_gchandle_free (klass->ref_info_handle);
741                 klass->ref_info_handle = 0;
742         }
743 }
744
745 static void
746 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
747 {
748         MONO_REQ_GC_NEUTRAL_MODE;
749
750         int i;
751         MonoGenericInst *class_inst;
752         MonoClass *klass;
753
754         g_assert (gclass);
755
756         class_inst = gclass->context.class_inst;
757
758         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
759         klass = gclass->container_class;
760         sigbuffer_add_value (buf, klass->byval_arg.type);
761         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
762
763         sigbuffer_add_value (buf, class_inst->type_argc);
764         for (i = 0; i < class_inst->type_argc; ++i)
765                 encode_type (assembly, class_inst->type_argv [i], buf);
766
767 }
768
769 static void
770 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
771 {
772         MONO_REQ_GC_NEUTRAL_MODE;
773
774         if (!type) {
775                 g_assert_not_reached ();
776                 return;
777         }
778                 
779         if (type->byref)
780                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
781
782         switch (type->type){
783         case MONO_TYPE_VOID:
784         case MONO_TYPE_BOOLEAN:
785         case MONO_TYPE_CHAR:
786         case MONO_TYPE_I1:
787         case MONO_TYPE_U1:
788         case MONO_TYPE_I2:
789         case MONO_TYPE_U2:
790         case MONO_TYPE_I4:
791         case MONO_TYPE_U4:
792         case MONO_TYPE_I8:
793         case MONO_TYPE_U8:
794         case MONO_TYPE_R4:
795         case MONO_TYPE_R8:
796         case MONO_TYPE_I:
797         case MONO_TYPE_U:
798         case MONO_TYPE_STRING:
799         case MONO_TYPE_OBJECT:
800         case MONO_TYPE_TYPEDBYREF:
801                 sigbuffer_add_value (buf, type->type);
802                 break;
803         case MONO_TYPE_PTR:
804                 sigbuffer_add_value (buf, type->type);
805                 encode_type (assembly, type->data.type, buf);
806                 break;
807         case MONO_TYPE_SZARRAY:
808                 sigbuffer_add_value (buf, type->type);
809                 encode_type (assembly, &type->data.klass->byval_arg, buf);
810                 break;
811         case MONO_TYPE_VALUETYPE:
812         case MONO_TYPE_CLASS: {
813                 MonoClass *k = mono_class_from_mono_type (type);
814
815                 if (k->generic_container) {
816                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
817                         encode_generic_class (assembly, gclass, buf);
818                 } else {
819                         /*
820                          * Make sure we use the correct type.
821                          */
822                         sigbuffer_add_value (buf, k->byval_arg.type);
823                         /*
824                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
825                          * otherwise two typerefs could point to the same type, leading to
826                          * verification errors.
827                          */
828                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
829                 }
830                 break;
831         }
832         case MONO_TYPE_ARRAY:
833                 sigbuffer_add_value (buf, type->type);
834                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
835                 sigbuffer_add_value (buf, type->data.array->rank);
836                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
837                 sigbuffer_add_value (buf, 0);
838                 break;
839         case MONO_TYPE_GENERICINST:
840                 encode_generic_class (assembly, type->data.generic_class, buf);
841                 break;
842         case MONO_TYPE_VAR:
843         case MONO_TYPE_MVAR:
844                 sigbuffer_add_value (buf, type->type);
845                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
846                 break;
847         default:
848                 g_error ("need to encode type %x", type->type);
849         }
850 }
851
852 static void
853 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
854 {
855         MONO_REQ_GC_UNSAFE_MODE;
856
857         if (!type) {
858                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
859                 return;
860         }
861
862         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
863 }
864
865 static void
866 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
867 {
868         MONO_REQ_GC_UNSAFE_MODE;
869
870         int i;
871
872         if (modreq) {
873                 for (i = 0; i < mono_array_length (modreq); ++i) {
874                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
875                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
876                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
877                 }
878         }
879         if (modopt) {
880                 for (i = 0; i < mono_array_length (modopt); ++i) {
881                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
882                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
883                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
884                 }
885         }
886 }
887
888 #ifndef DISABLE_REFLECTION_EMIT
889 static guint32
890 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
891 {
892         MONO_REQ_GC_UNSAFE_MODE;
893
894         SigBuffer buf;
895         int i;
896         guint32 nparams =  sig->param_count;
897         guint32 idx;
898
899         if (!assembly->save)
900                 return 0;
901
902         sigbuffer_init (&buf, 32);
903         /*
904          * FIXME: vararg, explicit_this, differenc call_conv values...
905          */
906         idx = sig->call_convention;
907         if (sig->hasthis)
908                 idx |= 0x20; /* hasthis */
909         if (sig->generic_param_count)
910                 idx |= 0x10; /* generic */
911         sigbuffer_add_byte (&buf, idx);
912         if (sig->generic_param_count)
913                 sigbuffer_add_value (&buf, sig->generic_param_count);
914         sigbuffer_add_value (&buf, nparams);
915         encode_type (assembly, sig->ret, &buf);
916         for (i = 0; i < nparams; ++i) {
917                 if (i == sig->sentinelpos)
918                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
919                 encode_type (assembly, sig->params [i], &buf);
920         }
921         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
922         sigbuffer_free (&buf);
923         return idx;
924 }
925 #endif
926
927 static guint32
928 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
929 {
930         MONO_REQ_GC_UNSAFE_MODE;
931
932         /*
933          * FIXME: reuse code from method_encode_signature().
934          */
935         SigBuffer buf;
936         int i;
937         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
938         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
939         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
940         guint32 idx;
941
942         sigbuffer_init (&buf, 32);
943         /* LAMESPEC: all the call conv spec is foobared */
944         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
945         if (mb->call_conv & 2)
946                 idx |= 0x5; /* vararg */
947         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
948                 idx |= 0x20; /* hasthis */
949         if (ngparams)
950                 idx |= 0x10; /* generic */
951         sigbuffer_add_byte (&buf, idx);
952         if (ngparams)
953                 sigbuffer_add_value (&buf, ngparams);
954         sigbuffer_add_value (&buf, nparams + notypes);
955         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
956         encode_reflection_type (assembly, mb->rtype, &buf);
957         for (i = 0; i < nparams; ++i) {
958                 MonoArray *modreq = NULL;
959                 MonoArray *modopt = NULL;
960                 MonoReflectionType *pt;
961
962                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
963                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
964                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
965                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
966                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
967                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
968                 encode_reflection_type (assembly, pt, &buf);
969         }
970         if (notypes)
971                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
972         for (i = 0; i < notypes; ++i) {
973                 MonoReflectionType *pt;
974
975                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
976                 encode_reflection_type (assembly, pt, &buf);
977         }
978
979         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
980         sigbuffer_free (&buf);
981         return idx;
982 }
983
984 static guint32
985 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
986 {
987         MONO_REQ_GC_UNSAFE_MODE;
988
989         MonoDynamicTable *table;
990         guint32 *values;
991         guint32 idx, sig_idx;
992         guint nl = mono_array_length (ilgen->locals);
993         SigBuffer buf;
994         int i;
995
996         sigbuffer_init (&buf, 32);
997         sigbuffer_add_value (&buf, 0x07);
998         sigbuffer_add_value (&buf, nl);
999         for (i = 0; i < nl; ++i) {
1000                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1001                 
1002                 if (lb->is_pinned)
1003                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1004                 
1005                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1006         }
1007         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1008         sigbuffer_free (&buf);
1009
1010         if (assembly->standalonesig_cache == NULL)
1011                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1012         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1013         if (idx)
1014                 return idx;
1015
1016         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1017         idx = table->next_idx ++;
1018         table->rows ++;
1019         alloc_table (table, table->rows);
1020         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1021
1022         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1023
1024         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1025
1026         return idx;
1027 }
1028
1029 static guint32
1030 method_count_clauses (MonoReflectionILGen *ilgen)
1031 {
1032         MONO_REQ_GC_UNSAFE_MODE;
1033
1034         guint32 num_clauses = 0;
1035         int i;
1036
1037         MonoILExceptionInfo *ex_info;
1038         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1039                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1040                 if (ex_info->handlers)
1041                         num_clauses += mono_array_length (ex_info->handlers);
1042                 else
1043                         num_clauses++;
1044         }
1045
1046         return num_clauses;
1047 }
1048
1049 #ifndef DISABLE_REFLECTION_EMIT
1050 static MonoExceptionClause*
1051 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1052 {
1053         MONO_REQ_GC_UNSAFE_MODE;
1054
1055         MonoExceptionClause *clauses;
1056         MonoExceptionClause *clause;
1057         MonoILExceptionInfo *ex_info;
1058         MonoILExceptionBlock *ex_block;
1059         guint32 finally_start;
1060         int i, j, clause_index;;
1061
1062         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1063
1064         clause_index = 0;
1065         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1066                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1067                 finally_start = ex_info->start + ex_info->len;
1068                 if (!ex_info->handlers)
1069                         continue;
1070                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1071                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1072                         clause = &(clauses [clause_index]);
1073
1074                         clause->flags = ex_block->type;
1075                         clause->try_offset = ex_info->start;
1076
1077                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1078                                 clause->try_len = finally_start - ex_info->start;
1079                         else
1080                                 clause->try_len = ex_info->len;
1081                         clause->handler_offset = ex_block->start;
1082                         clause->handler_len = ex_block->len;
1083                         if (ex_block->extype) {
1084                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1085                         } else {
1086                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1087                                         clause->data.filter_offset = ex_block->filter_offset;
1088                                 else
1089                                         clause->data.filter_offset = 0;
1090                         }
1091                         finally_start = ex_block->start + ex_block->len;
1092
1093                         clause_index ++;
1094                 }
1095         }
1096
1097         return clauses;
1098 }
1099 #endif /* !DISABLE_REFLECTION_EMIT */
1100
1101 static guint32
1102 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
1103 {
1104         MONO_REQ_GC_UNSAFE_MODE;
1105
1106         char flags = 0;
1107         guint32 idx;
1108         guint32 code_size;
1109         gint32 max_stack, i;
1110         gint32 num_locals = 0;
1111         gint32 num_exception = 0;
1112         gint maybe_small;
1113         guint32 fat_flags;
1114         char fat_header [12];
1115         guint32 int_value;
1116         guint16 short_value;
1117         guint32 local_sig = 0;
1118         guint32 header_size = 12;
1119         MonoArray *code;
1120
1121         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1122                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1123                 return 0;
1124
1125         /*if (mb->name)
1126                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1127         if (mb->ilgen) {
1128                 code = mb->ilgen->code;
1129                 code_size = mb->ilgen->code_len;
1130                 max_stack = mb->ilgen->max_stack;
1131                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1132                 if (mb->ilgen->ex_handlers)
1133                         num_exception = method_count_clauses (mb->ilgen);
1134         } else {
1135                 code = mb->code;
1136                 if (code == NULL){
1137                         char *name = mono_string_to_utf8 (mb->name);
1138                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1139                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1140                         g_free (str);
1141                         g_free (name);
1142                         mono_raise_exception (exception);
1143                 }
1144
1145                 code_size = mono_array_length (code);
1146                 max_stack = 8; /* we probably need to run a verifier on the code... */
1147         }
1148
1149         stream_data_align (&assembly->code);
1150
1151         /* check for exceptions, maxstack, locals */
1152         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1153         if (maybe_small) {
1154                 if (code_size < 64 && !(code_size & 1)) {
1155                         flags = (code_size << 2) | 0x2;
1156                 } else if (code_size < 32 && (code_size & 1)) {
1157                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1158                 } else {
1159                         goto fat_header;
1160                 }
1161                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1162                 /* add to the fixup todo list */
1163                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1164                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1165                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1166                 return assembly->text_rva + idx;
1167         } 
1168 fat_header:
1169         if (num_locals)
1170                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1171         /* 
1172          * FIXME: need to set also the header size in fat_flags.
1173          * (and more sects and init locals flags)
1174          */
1175         fat_flags =  0x03;
1176         if (num_exception)
1177                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1178         if (mb->init_locals)
1179                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1180         fat_header [0] = fat_flags;
1181         fat_header [1] = (header_size / 4 ) << 4;
1182         short_value = GUINT16_TO_LE (max_stack);
1183         memcpy (fat_header + 2, &short_value, 2);
1184         int_value = GUINT32_TO_LE (code_size);
1185         memcpy (fat_header + 4, &int_value, 4);
1186         int_value = GUINT32_TO_LE (local_sig);
1187         memcpy (fat_header + 8, &int_value, 4);
1188         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1189         /* add to the fixup todo list */
1190         if (mb->ilgen && mb->ilgen->num_token_fixups)
1191                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1192         
1193         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1194         if (num_exception) {
1195                 unsigned char sheader [4];
1196                 MonoILExceptionInfo * ex_info;
1197                 MonoILExceptionBlock * ex_block;
1198                 int j;
1199
1200                 stream_data_align (&assembly->code);
1201                 /* always use fat format for now */
1202                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1203                 num_exception *= 6 * sizeof (guint32);
1204                 num_exception += 4; /* include the size of the header */
1205                 sheader [1] = num_exception & 0xff;
1206                 sheader [2] = (num_exception >> 8) & 0xff;
1207                 sheader [3] = (num_exception >> 16) & 0xff;
1208                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1209                 /* fat header, so we are already aligned */
1210                 /* reverse order */
1211                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1212                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1213                         if (ex_info->handlers) {
1214                                 int finally_start = ex_info->start + ex_info->len;
1215                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1216                                         guint32 val;
1217                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1218                                         /* the flags */
1219                                         val = GUINT32_TO_LE (ex_block->type);
1220                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1221                                         /* try offset */
1222                                         val = GUINT32_TO_LE (ex_info->start);
1223                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1224                                         /* need fault, too, probably */
1225                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1226                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1227                                         else
1228                                                 val = GUINT32_TO_LE (ex_info->len);
1229                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1230                                         /* handler offset */
1231                                         val = GUINT32_TO_LE (ex_block->start);
1232                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1233                                         /* handler len */
1234                                         val = GUINT32_TO_LE (ex_block->len);
1235                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1236                                         finally_start = ex_block->start + ex_block->len;
1237                                         if (ex_block->extype) {
1238                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1239                                         } else {
1240                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1241                                                         val = ex_block->filter_offset;
1242                                                 else
1243                                                         val = 0;
1244                                         }
1245                                         val = GUINT32_TO_LE (val);
1246                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1247                                         /*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", 
1248                                                         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);*/
1249                                 }
1250                         } else {
1251                                 g_error ("No clauses for ex info block %d", i);
1252                         }
1253                 }
1254         }
1255         return assembly->text_rva + idx;
1256 }
1257
1258 static guint32
1259 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1260 {
1261         MONO_REQ_GC_NEUTRAL_MODE;
1262
1263         int i;
1264         MonoDynamicTable *table;
1265         guint32 *values;
1266         
1267         table = &assembly->tables [table_idx];
1268
1269         g_assert (col < table->columns);
1270
1271         values = table->values + table->columns;
1272         for (i = 1; i <= table->rows; ++i) {
1273                 if (values [col] == token)
1274                         return i;
1275                 values += table->columns;
1276         }
1277         return 0;
1278 }
1279
1280 /*
1281  * LOCKING: Acquires the loader lock. 
1282  */
1283 static MonoCustomAttrInfo*
1284 lookup_custom_attr (MonoImage *image, gpointer member)
1285 {
1286         MONO_REQ_GC_NEUTRAL_MODE;
1287
1288         MonoCustomAttrInfo* res;
1289
1290         res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1291
1292         if (!res)
1293                 return NULL;
1294
1295         res = g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1296         res->cached = 0;
1297         return res;
1298 }
1299
1300 static gboolean
1301 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1302 {
1303         MONO_REQ_GC_UNSAFE_MODE;
1304
1305         /* FIXME: Need to do more checks */
1306         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1307                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1308
1309                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1310                         return FALSE;
1311         }
1312
1313         return TRUE;
1314 }
1315
1316 static MonoCustomAttrInfo*
1317 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1318 {
1319         MONO_REQ_GC_UNSAFE_MODE;
1320
1321         int i, index, count, not_visible;
1322         MonoCustomAttrInfo *ainfo;
1323         MonoReflectionCustomAttr *cattr;
1324
1325         if (!cattrs)
1326                 return NULL;
1327         /* FIXME: check in assembly the Run flag is set */
1328
1329         count = mono_array_length (cattrs);
1330
1331         /* Skip nonpublic attributes since MS.NET seems to do the same */
1332         /* FIXME: This needs to be done more globally */
1333         not_visible = 0;
1334         for (i = 0; i < count; ++i) {
1335                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1336                 if (!custom_attr_visible (image, cattr))
1337                         not_visible ++;
1338         }
1339         count -= not_visible;
1340
1341         ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1342
1343         ainfo->image = image;
1344         ainfo->num_attrs = count;
1345         ainfo->cached = alloc_img != NULL;
1346         index = 0;
1347         for (i = 0; i < count; ++i) {
1348                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1349                 if (custom_attr_visible (image, cattr)) {
1350                         unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1351                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1352                         ainfo->attrs [index].ctor = cattr->ctor->method;
1353                         ainfo->attrs [index].data = saved;
1354                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1355                         index ++;
1356                 }
1357         }
1358
1359         return ainfo;
1360 }
1361
1362 #ifndef DISABLE_REFLECTION_EMIT
1363 /*
1364  * LOCKING: Acquires the loader lock. 
1365  */
1366 static void
1367 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1368 {
1369         MONO_REQ_GC_UNSAFE_MODE;
1370
1371         MonoCustomAttrInfo *ainfo, *tmp;
1372
1373         if (!cattrs || !mono_array_length (cattrs))
1374                 return;
1375
1376         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1377
1378         mono_loader_lock ();
1379         tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1380         if (tmp)
1381                 mono_custom_attrs_free (tmp);
1382         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1383         mono_loader_unlock ();
1384
1385 }
1386 #endif
1387
1388 void
1389 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1390 {
1391         MONO_REQ_GC_NEUTRAL_MODE;
1392
1393         if (!ainfo->cached)
1394                 g_free (ainfo);
1395 }
1396
1397 /*
1398  * idx is the table index of the object
1399  * type is one of MONO_CUSTOM_ATTR_*
1400  */
1401 static void
1402 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1403 {
1404         MONO_REQ_GC_UNSAFE_MODE;
1405
1406         MonoDynamicTable *table;
1407         MonoReflectionCustomAttr *cattr;
1408         guint32 *values;
1409         guint32 count, i, token;
1410         char blob_size [6];
1411         char *p = blob_size;
1412         
1413         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1414         if (!cattrs)
1415                 return;
1416         count = mono_array_length (cattrs);
1417         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1418         table->rows += count;
1419         alloc_table (table, table->rows);
1420         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1421         idx <<= MONO_CUSTOM_ATTR_BITS;
1422         idx |= type;
1423         for (i = 0; i < count; ++i) {
1424                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1425                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1426                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1427                 type = mono_metadata_token_index (token);
1428                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1429                 switch (mono_metadata_token_table (token)) {
1430                 case MONO_TABLE_METHOD:
1431                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1432                         /*
1433                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1434                          * method, not the one returned by mono_image_create_token ().
1435                          */
1436                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1437                         break;
1438                 case MONO_TABLE_MEMBERREF:
1439                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1440                         break;
1441                 default:
1442                         g_warning ("got wrong token in custom attr");
1443                         continue;
1444                 }
1445                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1446                 p = blob_size;
1447                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1448                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1449                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1450                 values += MONO_CUSTOM_ATTR_SIZE;
1451                 ++table->next_idx;
1452         }
1453 }
1454
1455 static void
1456 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1457 {
1458         MONO_REQ_GC_UNSAFE_MODE;
1459
1460         MonoDynamicTable *table;
1461         guint32 *values;
1462         guint32 count, i, idx;
1463         MonoReflectionPermissionSet *perm;
1464
1465         if (!permissions)
1466                 return;
1467
1468         count = mono_array_length (permissions);
1469         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1470         table->rows += count;
1471         alloc_table (table, table->rows);
1472
1473         for (i = 0; i < mono_array_length (permissions); ++i) {
1474                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1475
1476                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1477
1478                 idx = mono_metadata_token_index (parent_token);
1479                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1480                 switch (mono_metadata_token_table (parent_token)) {
1481                 case MONO_TABLE_TYPEDEF:
1482                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1483                         break;
1484                 case MONO_TABLE_METHOD:
1485                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1486                         break;
1487                 case MONO_TABLE_ASSEMBLY:
1488                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1489                         break;
1490                 default:
1491                         g_assert_not_reached ();
1492                 }
1493
1494                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1495                 values [MONO_DECL_SECURITY_PARENT] = idx;
1496                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1497
1498                 ++table->next_idx;
1499         }
1500 }
1501
1502 /*
1503  * Fill in the MethodDef and ParamDef tables for a method.
1504  * This is used for both normal methods and constructors.
1505  */
1506 static void
1507 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1508 {
1509         MONO_REQ_GC_UNSAFE_MODE;
1510
1511         MonoDynamicTable *table;
1512         guint32 *values;
1513         guint i, count;
1514
1515         /* room in this table is already allocated */
1516         table = &assembly->tables [MONO_TABLE_METHOD];
1517         *mb->table_idx = table->next_idx ++;
1518         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1519         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1520         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1521         values [MONO_METHOD_FLAGS] = mb->attrs;
1522         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1523         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1524         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1525         
1526         table = &assembly->tables [MONO_TABLE_PARAM];
1527         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1528
1529         mono_image_add_decl_security (assembly, 
1530                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1531
1532         if (mb->pinfo) {
1533                 MonoDynamicTable *mtable;
1534                 guint32 *mvalues;
1535                 
1536                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1537                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1538                 
1539                 count = 0;
1540                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1541                         if (mono_array_get (mb->pinfo, gpointer, i))
1542                                 count++;
1543                 }
1544                 table->rows += count;
1545                 alloc_table (table, table->rows);
1546                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1547                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1548                         MonoReflectionParamBuilder *pb;
1549                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1550                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1551                                 values [MONO_PARAM_SEQUENCE] = i;
1552                                 if (pb->name != NULL) {
1553                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1554                                 } else {
1555                                         values [MONO_PARAM_NAME] = 0;
1556                                 }
1557                                 values += MONO_PARAM_SIZE;
1558                                 if (pb->marshal_info) {
1559                                         mtable->rows++;
1560                                         alloc_table (mtable, mtable->rows);
1561                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1562                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1563                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1564                                 }
1565                                 pb->table_idx = table->next_idx++;
1566                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1567                                         guint32 field_type = 0;
1568                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1569                                         mtable->rows ++;
1570                                         alloc_table (mtable, mtable->rows);
1571                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1572                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1573                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1574                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1575                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1576                                 }
1577                         }
1578                 }
1579         }
1580 }
1581
1582 #ifndef DISABLE_REFLECTION_EMIT
1583 static void
1584 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1585 {
1586         MONO_REQ_GC_UNSAFE_MODE;
1587
1588         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1589
1590         rmb->ilgen = mb->ilgen;
1591         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1592         rmb->parameters = mb->parameters;
1593         rmb->generic_params = mb->generic_params;
1594         rmb->generic_container = mb->generic_container;
1595         rmb->opt_types = NULL;
1596         rmb->pinfo = mb->pinfo;
1597         rmb->attrs = mb->attrs;
1598         rmb->iattrs = mb->iattrs;
1599         rmb->call_conv = mb->call_conv;
1600         rmb->code = mb->code;
1601         rmb->type = mb->type;
1602         rmb->name = mb->name;
1603         rmb->table_idx = &mb->table_idx;
1604         rmb->init_locals = mb->init_locals;
1605         rmb->skip_visibility = FALSE;
1606         rmb->return_modreq = mb->return_modreq;
1607         rmb->return_modopt = mb->return_modopt;
1608         rmb->param_modreq = mb->param_modreq;
1609         rmb->param_modopt = mb->param_modopt;
1610         rmb->permissions = mb->permissions;
1611         rmb->mhandle = mb->mhandle;
1612         rmb->nrefs = 0;
1613         rmb->refs = NULL;
1614
1615         if (mb->dll) {
1616                 rmb->charset = mb->charset;
1617                 rmb->extra_flags = mb->extra_flags;
1618                 rmb->native_cc = mb->native_cc;
1619                 rmb->dllentry = mb->dllentry;
1620                 rmb->dll = mb->dll;
1621         }
1622 }
1623
1624 static void
1625 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1626 {
1627         MONO_REQ_GC_UNSAFE_MODE;
1628
1629         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1630
1631         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1632
1633         rmb->ilgen = mb->ilgen;
1634         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1635         rmb->parameters = mb->parameters;
1636         rmb->generic_params = NULL;
1637         rmb->generic_container = NULL;
1638         rmb->opt_types = NULL;
1639         rmb->pinfo = mb->pinfo;
1640         rmb->attrs = mb->attrs;
1641         rmb->iattrs = mb->iattrs;
1642         rmb->call_conv = mb->call_conv;
1643         rmb->code = NULL;
1644         rmb->type = mb->type;
1645         rmb->name = mono_string_new (mono_domain_get (), name);
1646         rmb->table_idx = &mb->table_idx;
1647         rmb->init_locals = mb->init_locals;
1648         rmb->skip_visibility = FALSE;
1649         rmb->return_modreq = NULL;
1650         rmb->return_modopt = NULL;
1651         rmb->param_modreq = mb->param_modreq;
1652         rmb->param_modopt = mb->param_modopt;
1653         rmb->permissions = mb->permissions;
1654         rmb->mhandle = mb->mhandle;
1655         rmb->nrefs = 0;
1656         rmb->refs = NULL;
1657 }
1658
1659 static void
1660 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1661 {
1662         MONO_REQ_GC_UNSAFE_MODE;
1663
1664         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1665
1666         rmb->ilgen = mb->ilgen;
1667         rmb->rtype = mb->rtype;
1668         rmb->parameters = mb->parameters;
1669         rmb->generic_params = NULL;
1670         rmb->generic_container = NULL;
1671         rmb->opt_types = NULL;
1672         rmb->pinfo = NULL;
1673         rmb->attrs = mb->attrs;
1674         rmb->iattrs = 0;
1675         rmb->call_conv = mb->call_conv;
1676         rmb->code = NULL;
1677         rmb->type = (MonoObject *) mb->owner;
1678         rmb->name = mb->name;
1679         rmb->table_idx = NULL;
1680         rmb->init_locals = mb->init_locals;
1681         rmb->skip_visibility = mb->skip_visibility;
1682         rmb->return_modreq = NULL;
1683         rmb->return_modopt = NULL;
1684         rmb->param_modreq = NULL;
1685         rmb->param_modopt = NULL;
1686         rmb->permissions = NULL;
1687         rmb->mhandle = mb->mhandle;
1688         rmb->nrefs = 0;
1689         rmb->refs = NULL;
1690 }       
1691 #endif
1692
1693 static void
1694 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1695 {
1696         MONO_REQ_GC_UNSAFE_MODE;
1697
1698         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1699         MonoDynamicTable *table;
1700         guint32 *values;
1701         guint32 tok;
1702         MonoReflectionMethod *m;
1703         int i;
1704
1705         if (!mb->override_methods)
1706                 return;
1707
1708         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1709                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1710
1711                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1712                 table->rows ++;
1713                 alloc_table (table, table->rows);
1714                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1715                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1716                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1717
1718                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE);
1719                 switch (mono_metadata_token_table (tok)) {
1720                 case MONO_TABLE_MEMBERREF:
1721                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1722                         break;
1723                 case MONO_TABLE_METHOD:
1724                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1725                         break;
1726                 default:
1727                         g_assert_not_reached ();
1728                 }
1729                 values [MONO_METHODIMPL_DECLARATION] = tok;
1730         }
1731 }
1732
1733 #ifndef DISABLE_REFLECTION_EMIT
1734 static void
1735 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1736 {
1737         MONO_REQ_GC_UNSAFE_MODE;
1738
1739         MonoDynamicTable *table;
1740         guint32 *values;
1741         ReflectionMethodBuilder rmb;
1742         int i;
1743
1744         reflection_methodbuilder_from_method_builder (&rmb, mb);
1745
1746         mono_image_basic_method (&rmb, assembly);
1747         mb->table_idx = *rmb.table_idx;
1748
1749         if (mb->dll) { /* It's a P/Invoke method */
1750                 guint32 moduleref;
1751                 /* map CharSet values to on-disk values */
1752                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1753                 int extra_flags = mb->extra_flags;
1754                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1755                 table->rows ++;
1756                 alloc_table (table, table->rows);
1757                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1758                 
1759                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1760                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1761                 if (mb->dllentry)
1762                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1763                 else
1764                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1765                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1766                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1767                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1768                         table->rows ++;
1769                         alloc_table (table, table->rows);
1770                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1771                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1772                 }
1773         }
1774
1775         if (mb->generic_params) {
1776                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1777                 table->rows += mono_array_length (mb->generic_params);
1778                 alloc_table (table, table->rows);
1779                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1780                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1781
1782                         mono_image_get_generic_param_info (
1783                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1784                 }
1785         }
1786
1787 }
1788
1789 static void
1790 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1791 {
1792         MONO_REQ_GC_UNSAFE_MODE;
1793
1794         ReflectionMethodBuilder rmb;
1795
1796         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1797
1798         mono_image_basic_method (&rmb, assembly);
1799         mb->table_idx = *rmb.table_idx;
1800 }
1801 #endif
1802
1803 static char*
1804 type_get_fully_qualified_name (MonoType *type)
1805 {
1806         MONO_REQ_GC_NEUTRAL_MODE;
1807
1808         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1809 }
1810
1811 static char*
1812 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1813 {
1814         MONO_REQ_GC_UNSAFE_MODE;
1815
1816         MonoClass *klass;
1817         MonoAssembly *ta;
1818
1819         klass = mono_class_from_mono_type (type);
1820         if (!klass) 
1821                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1822         ta = klass->image->assembly;
1823         if (assembly_is_dynamic (ta) || (ta == ass)) {
1824                 if (klass->generic_class || klass->generic_container)
1825                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1826                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1827                 else
1828                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1829         }
1830
1831         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1832 }
1833
1834 #ifndef DISABLE_REFLECTION_EMIT
1835 /*field_image is the image to which the eventual custom mods have been encoded against*/
1836 static guint32
1837 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1838 {
1839         MONO_REQ_GC_NEUTRAL_MODE;
1840
1841         SigBuffer buf;
1842         guint32 idx, i, token;
1843
1844         if (!assembly->save)
1845                 return 0;
1846
1847         sigbuffer_init (&buf, 32);
1848         
1849         sigbuffer_add_value (&buf, 0x06);
1850         /* encode custom attributes before the type */
1851         if (type->num_mods) {
1852                 for (i = 0; i < type->num_mods; ++i) {
1853                         if (field_image) {
1854                                 MonoError error;
1855                                 MonoClass *class = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1856                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1857
1858                                 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1859                         } else {
1860                                 token = type->modifiers [i].token;
1861                         }
1862
1863                         if (type->modifiers [i].required)
1864                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1865                         else
1866                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1867
1868                         sigbuffer_add_value (&buf, token);
1869                 }
1870         }
1871         encode_type (assembly, type, &buf);
1872         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1873         sigbuffer_free (&buf);
1874         return idx;
1875 }
1876 #endif
1877
1878 static guint32
1879 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1880 {
1881         MONO_REQ_GC_UNSAFE_MODE;
1882
1883         SigBuffer buf;
1884         guint32 idx;
1885         guint32 typespec = 0;
1886         MonoType *type;
1887         MonoClass *class;
1888
1889         init_type_builder_generics (fb->type);
1890
1891         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
1892         class = mono_class_from_mono_type (type);
1893
1894         sigbuffer_init (&buf, 32);
1895         
1896         sigbuffer_add_value (&buf, 0x06);
1897         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
1898         /* encode custom attributes before the type */
1899
1900         if (class->generic_container)
1901                 typespec = create_typespec (assembly, type);
1902
1903         if (typespec) {
1904                 MonoGenericClass *gclass;
1905                 gclass = mono_metadata_lookup_generic_class (class, class->generic_container->context.class_inst, TRUE);
1906                 encode_generic_class (assembly, gclass, &buf);
1907         } else {
1908                 encode_type (assembly, type, &buf);
1909         }
1910         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1911         sigbuffer_free (&buf);
1912         return idx;
1913 }
1914
1915 static guint32
1916 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type)
1917 {
1918         MONO_REQ_GC_UNSAFE_MODE;
1919
1920         char blob_size [64];
1921         char *b = blob_size;
1922         char *box_val;
1923         char* buf;
1924         guint32 idx = 0, len = 0, dummy = 0;
1925
1926         buf = g_malloc (64);
1927         if (!val) {
1928                 *ret_type = MONO_TYPE_CLASS;
1929                 len = 4;
1930                 box_val = (char*)&dummy;
1931         } else {
1932                 box_val = ((char*)val) + sizeof (MonoObject);
1933                 *ret_type = val->vtable->klass->byval_arg.type;
1934         }
1935 handle_enum:
1936         switch (*ret_type) {
1937         case MONO_TYPE_BOOLEAN:
1938         case MONO_TYPE_U1:
1939         case MONO_TYPE_I1:
1940                 len = 1;
1941                 break;
1942         case MONO_TYPE_CHAR:
1943         case MONO_TYPE_U2:
1944         case MONO_TYPE_I2:
1945                 len = 2;
1946                 break;
1947         case MONO_TYPE_U4:
1948         case MONO_TYPE_I4:
1949         case MONO_TYPE_R4:
1950                 len = 4;
1951                 break;
1952         case MONO_TYPE_U8:
1953         case MONO_TYPE_I8:
1954                 len = 8;
1955                 break;
1956         case MONO_TYPE_R8:
1957                 len = 8;
1958                 break;
1959         case MONO_TYPE_VALUETYPE: {
1960                 MonoClass *klass = val->vtable->klass;
1961                 
1962                 if (klass->enumtype) {
1963                         *ret_type = mono_class_enum_basetype (klass)->type;
1964                         goto handle_enum;
1965                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
1966                         len = 8;
1967                 } else 
1968                         g_error ("we can't encode valuetypes, we should have never reached this line");
1969                 break;
1970         }
1971         case MONO_TYPE_CLASS:
1972                 break;
1973         case MONO_TYPE_STRING: {
1974                 MonoString *str = (MonoString*)val;
1975                 /* there is no signature */
1976                 len = str->length * 2;
1977                 mono_metadata_encode_value (len, b, &b);
1978 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1979                 {
1980                         char *swapped = g_malloc (2 * mono_string_length (str));
1981                         const char *p = (const char*)mono_string_chars (str);
1982
1983                         swap_with_size (swapped, p, 2, mono_string_length (str));
1984                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1985                         g_free (swapped);
1986                 }
1987 #else
1988                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1989 #endif
1990
1991                 g_free (buf);
1992                 return idx;
1993         }
1994         case MONO_TYPE_GENERICINST:
1995                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1996                 goto handle_enum;
1997         default:
1998                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1999         }
2000
2001         /* there is no signature */
2002         mono_metadata_encode_value (len, b, &b);
2003 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2004         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2005         swap_with_size (blob_size, box_val, len, 1);
2006         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2007 #else
2008         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2009 #endif
2010
2011         g_free (buf);
2012         return idx;
2013 }
2014
2015 static guint32
2016 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2017 {
2018         MONO_REQ_GC_UNSAFE_MODE;
2019
2020         char *str;
2021         SigBuffer buf;
2022         guint32 idx, len;
2023
2024         sigbuffer_init (&buf, 32);
2025
2026         sigbuffer_add_value (&buf, minfo->type);
2027
2028         switch (minfo->type) {
2029         case MONO_NATIVE_BYVALTSTR:
2030         case MONO_NATIVE_BYVALARRAY:
2031                 sigbuffer_add_value (&buf, minfo->count);
2032                 break;
2033         case MONO_NATIVE_LPARRAY:
2034                 if (minfo->eltype || minfo->has_size) {
2035                         sigbuffer_add_value (&buf, minfo->eltype);
2036                         if (minfo->has_size) {
2037                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2038                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2039
2040                                 /* LAMESPEC: ElemMult is undocumented */
2041                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2042                         }
2043                 }
2044                 break;
2045         case MONO_NATIVE_SAFEARRAY:
2046                 if (minfo->eltype)
2047                         sigbuffer_add_value (&buf, minfo->eltype);
2048                 break;
2049         case MONO_NATIVE_CUSTOM:
2050                 if (minfo->guid) {
2051                         str = mono_string_to_utf8 (minfo->guid);
2052                         len = strlen (str);
2053                         sigbuffer_add_value (&buf, len);
2054                         sigbuffer_add_mem (&buf, str, len);
2055                         g_free (str);
2056                 } else {
2057                         sigbuffer_add_value (&buf, 0);
2058                 }
2059                 /* native type name */
2060                 sigbuffer_add_value (&buf, 0);
2061                 /* custom marshaler type name */
2062                 if (minfo->marshaltype || minfo->marshaltyperef) {
2063                         if (minfo->marshaltyperef)
2064                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2065                         else
2066                                 str = mono_string_to_utf8 (minfo->marshaltype);
2067                         len = strlen (str);
2068                         sigbuffer_add_value (&buf, len);
2069                         sigbuffer_add_mem (&buf, str, len);
2070                         g_free (str);
2071                 } else {
2072                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2073                         sigbuffer_add_value (&buf, 0);
2074                 }
2075                 if (minfo->mcookie) {
2076                         str = mono_string_to_utf8 (minfo->mcookie);
2077                         len = strlen (str);
2078                         sigbuffer_add_value (&buf, len);
2079                         sigbuffer_add_mem (&buf, str, len);
2080                         g_free (str);
2081                 } else {
2082                         sigbuffer_add_value (&buf, 0);
2083                 }
2084                 break;
2085         default:
2086                 break;
2087         }
2088         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2089         sigbuffer_free (&buf);
2090         return idx;
2091 }
2092
2093 static void
2094 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2095 {
2096         MONO_REQ_GC_UNSAFE_MODE;
2097
2098         MonoDynamicTable *table;
2099         guint32 *values;
2100
2101         /* maybe this fixup should be done in the C# code */
2102         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2103                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2104         table = &assembly->tables [MONO_TABLE_FIELD];
2105         fb->table_idx = table->next_idx ++;
2106         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2107         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2108         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2109         values [MONO_FIELD_FLAGS] = fb->attrs;
2110         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2111
2112         if (fb->offset != -1) {
2113                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2114                 table->rows ++;
2115                 alloc_table (table, table->rows);
2116                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2117                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2118                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2119         }
2120         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2121                 guint32 field_type = 0;
2122                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2123                 table->rows ++;
2124                 alloc_table (table, table->rows);
2125                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2126                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2127                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2128                 values [MONO_CONSTANT_TYPE] = field_type;
2129                 values [MONO_CONSTANT_PADDING] = 0;
2130         }
2131         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2132                 guint32 rva_idx;
2133                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2134                 table->rows ++;
2135                 alloc_table (table, table->rows);
2136                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2137                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2138                 /*
2139                  * We store it in the code section because it's simpler for now.
2140                  */
2141                 if (fb->rva_data) {
2142                         if (mono_array_length (fb->rva_data) >= 10)
2143                                 stream_data_align (&assembly->code);
2144                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2145                 } else
2146                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2147                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2148         }
2149         if (fb->marshal_info) {
2150                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2151                 table->rows ++;
2152                 alloc_table (table, table->rows);
2153                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2154                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2155                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2156         }
2157 }
2158
2159 static guint32
2160 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2161 {
2162         MONO_REQ_GC_UNSAFE_MODE;
2163
2164         SigBuffer buf;
2165         guint32 nparams = 0;
2166         MonoReflectionMethodBuilder *mb = fb->get_method;
2167         MonoReflectionMethodBuilder *smb = fb->set_method;
2168         guint32 idx, i;
2169
2170         if (mb && mb->parameters)
2171                 nparams = mono_array_length (mb->parameters);
2172         if (!mb && smb && smb->parameters)
2173                 nparams = mono_array_length (smb->parameters) - 1;
2174         sigbuffer_init (&buf, 32);
2175         if (fb->call_conv & 0x20)
2176                 sigbuffer_add_byte (&buf, 0x28);
2177         else
2178                 sigbuffer_add_byte (&buf, 0x08);
2179         sigbuffer_add_value (&buf, nparams);
2180         if (mb) {
2181                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2182                 for (i = 0; i < nparams; ++i) {
2183                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2184                         encode_reflection_type (assembly, pt, &buf);
2185                 }
2186         } else if (smb && smb->parameters) {
2187                 /* the property type is the last param */
2188                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2189                 for (i = 0; i < nparams; ++i) {
2190                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2191                         encode_reflection_type (assembly, pt, &buf);
2192                 }
2193         } else {
2194                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2195         }
2196
2197         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2198         sigbuffer_free (&buf);
2199         return idx;
2200 }
2201
2202 static void
2203 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2204 {
2205         MONO_REQ_GC_UNSAFE_MODE;
2206
2207         MonoDynamicTable *table;
2208         guint32 *values;
2209         guint num_methods = 0;
2210         guint32 semaidx;
2211
2212         /* 
2213          * we need to set things in the following tables:
2214          * PROPERTYMAP (info already filled in _get_type_info ())
2215          * PROPERTY    (rows already preallocated in _get_type_info ())
2216          * METHOD      (method info already done with the generic method code)
2217          * METHODSEMANTICS
2218          * CONSTANT
2219          */
2220         table = &assembly->tables [MONO_TABLE_PROPERTY];
2221         pb->table_idx = table->next_idx ++;
2222         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2223         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2224         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2225         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2226
2227         /* FIXME: we still don't handle 'other' methods */
2228         if (pb->get_method) num_methods ++;
2229         if (pb->set_method) num_methods ++;
2230
2231         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2232         table->rows += num_methods;
2233         alloc_table (table, table->rows);
2234
2235         if (pb->get_method) {
2236                 semaidx = table->next_idx ++;
2237                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2238                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2239                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2240                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2241         }
2242         if (pb->set_method) {
2243                 semaidx = table->next_idx ++;
2244                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2245                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2246                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2247                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2248         }
2249         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2250                 guint32 field_type = 0;
2251                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2252                 table->rows ++;
2253                 alloc_table (table, table->rows);
2254                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2255                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2256                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2257                 values [MONO_CONSTANT_TYPE] = field_type;
2258                 values [MONO_CONSTANT_PADDING] = 0;
2259         }
2260 }
2261
2262 static void
2263 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2264 {
2265         MONO_REQ_GC_UNSAFE_MODE;
2266
2267         MonoDynamicTable *table;
2268         guint32 *values;
2269         guint num_methods = 0;
2270         guint32 semaidx;
2271
2272         /* 
2273          * we need to set things in the following tables:
2274          * EVENTMAP (info already filled in _get_type_info ())
2275          * EVENT    (rows already preallocated in _get_type_info ())
2276          * METHOD      (method info already done with the generic method code)
2277          * METHODSEMANTICS
2278          */
2279         table = &assembly->tables [MONO_TABLE_EVENT];
2280         eb->table_idx = table->next_idx ++;
2281         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2282         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2283         values [MONO_EVENT_FLAGS] = eb->attrs;
2284         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2285
2286         /*
2287          * FIXME: we still don't handle 'other' methods 
2288          */
2289         if (eb->add_method) num_methods ++;
2290         if (eb->remove_method) num_methods ++;
2291         if (eb->raise_method) num_methods ++;
2292
2293         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2294         table->rows += num_methods;
2295         alloc_table (table, table->rows);
2296
2297         if (eb->add_method) {
2298                 semaidx = table->next_idx ++;
2299                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2300                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2301                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2302                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2303         }
2304         if (eb->remove_method) {
2305                 semaidx = table->next_idx ++;
2306                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2307                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2308                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2309                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2310         }
2311         if (eb->raise_method) {
2312                 semaidx = table->next_idx ++;
2313                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2314                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2315                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2316                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2317         }
2318 }
2319
2320 static void
2321 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2322 {
2323         MONO_REQ_GC_UNSAFE_MODE;
2324
2325         MonoDynamicTable *table;
2326         guint32 num_constraints, i;
2327         guint32 *values;
2328         guint32 table_idx;
2329
2330         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2331         num_constraints = gparam->iface_constraints ?
2332                 mono_array_length (gparam->iface_constraints) : 0;
2333         table->rows += num_constraints;
2334         if (gparam->base_type)
2335                 table->rows++;
2336         alloc_table (table, table->rows);
2337
2338         if (gparam->base_type) {
2339                 table_idx = table->next_idx ++;
2340                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2341
2342                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2343                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2344                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2345         }
2346
2347         for (i = 0; i < num_constraints; i++) {
2348                 MonoReflectionType *constraint = mono_array_get (
2349                         gparam->iface_constraints, gpointer, i);
2350
2351                 table_idx = table->next_idx ++;
2352                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2353
2354                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2355                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2356                         assembly, mono_reflection_type_get_handle (constraint));
2357         }
2358 }
2359
2360 static void
2361 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2362 {
2363         MONO_REQ_GC_UNSAFE_MODE;
2364
2365         GenericParamTableEntry *entry;
2366
2367         /*
2368          * The GenericParam table must be sorted according to the `owner' field.
2369          * We need to do this sorting prior to writing the GenericParamConstraint
2370          * table, since we have to use the final GenericParam table indices there
2371          * and they must also be sorted.
2372          */
2373
2374         entry = g_new0 (GenericParamTableEntry, 1);
2375         entry->owner = owner;
2376         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2377         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2378         entry->gparam = gparam;
2379         
2380         g_ptr_array_add (assembly->gen_params, entry);
2381 }
2382
2383 static void
2384 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2385 {
2386         MONO_REQ_GC_UNSAFE_MODE;
2387
2388         MonoDynamicTable *table;
2389         MonoGenericParam *param;
2390         guint32 *values;
2391         guint32 table_idx;
2392
2393         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2394         table_idx = table->next_idx ++;
2395         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2396
2397         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2398
2399         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2400         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2401         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2402         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2403
2404         mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2405
2406         encode_constraints (entry->gparam, table_idx, assembly);
2407 }
2408
2409 static guint32
2410 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2411 {
2412         MONO_REQ_GC_UNSAFE_MODE;
2413
2414         MonoDynamicTable *table;
2415         guint32 token;
2416         guint32 *values;
2417         guint32 cols [MONO_ASSEMBLY_SIZE];
2418         const char *pubkey;
2419         guint32 publen;
2420
2421         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2422                 return token;
2423
2424         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2425                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2426                 token = table->next_idx ++;
2427                 table->rows ++;
2428                 alloc_table (table, table->rows);
2429                 values = table->values + token * MONO_MODULEREF_SIZE;
2430                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2431
2432                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2433                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2434                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2435
2436                 return token;
2437         }
2438         
2439         if (assembly_is_dynamic (image->assembly))
2440                 /* FIXME: */
2441                 memset (cols, 0, sizeof (cols));
2442         else {
2443                 /* image->assembly->image is the manifest module */
2444                 image = image->assembly->image;
2445                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2446         }
2447
2448         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2449         token = table->next_idx ++;
2450         table->rows ++;
2451         alloc_table (table, table->rows);
2452         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2453         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2454         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2455         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2456         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2457         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2458         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2459         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2460         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2461
2462         if (strcmp ("", image->assembly->aname.culture)) {
2463                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2464                                 image->assembly->aname.culture);
2465         }
2466
2467         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2468                 guchar pubtoken [9];
2469                 pubtoken [0] = 8;
2470                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2471                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2472         } else {
2473                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2474         }
2475         token <<= MONO_RESOLUTION_SCOPE_BITS;
2476         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2477         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2478         return token;
2479 }
2480
2481 static guint32
2482 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2483 {
2484         MONO_REQ_GC_NEUTRAL_MODE;
2485
2486         MonoDynamicTable *table;
2487         guint32 *values;
2488         guint32 token;
2489         SigBuffer buf;
2490
2491         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2492                 return token;
2493
2494         sigbuffer_init (&buf, 32);
2495         switch (type->type) {
2496         case MONO_TYPE_FNPTR:
2497         case MONO_TYPE_PTR:
2498         case MONO_TYPE_SZARRAY:
2499         case MONO_TYPE_ARRAY:
2500         case MONO_TYPE_VAR:
2501         case MONO_TYPE_MVAR:
2502         case MONO_TYPE_GENERICINST:
2503                 encode_type (assembly, type, &buf);
2504                 break;
2505         case MONO_TYPE_CLASS:
2506         case MONO_TYPE_VALUETYPE: {
2507                 MonoClass *k = mono_class_from_mono_type (type);
2508                 if (!k || !k->generic_container) {
2509                         sigbuffer_free (&buf);
2510                         return 0;
2511                 }
2512                 encode_type (assembly, type, &buf);
2513                 break;
2514         }
2515         default:
2516                 sigbuffer_free (&buf);
2517                 return 0;
2518         }
2519
2520         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2521         if (assembly->save) {
2522                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2523                 alloc_table (table, table->rows + 1);
2524                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2525                 values [MONO_TYPESPEC_SIGNATURE] = token;
2526         }
2527         sigbuffer_free (&buf);
2528
2529         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2530         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2531         table->next_idx ++;
2532         return token;
2533 }
2534
2535 static guint32
2536 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2537 {
2538         MONO_REQ_GC_UNSAFE_MODE;
2539
2540         MonoDynamicTable *table;
2541         guint32 *values;
2542         guint32 token, scope, enclosing;
2543         MonoClass *klass;
2544
2545         /* if the type requires a typespec, we must try that first*/
2546         if (try_typespec && (token = create_typespec (assembly, type)))
2547                 return token;
2548         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2549         if (token)
2550                 return token;
2551         klass = mono_class_from_mono_type (type);
2552         if (!klass)
2553                 klass = mono_class_from_mono_type (type);
2554
2555         /*
2556          * If it's in the same module and not a generic type parameter:
2557          */
2558         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2559                         (type->type != MONO_TYPE_MVAR)) {
2560                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2561                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2562                 register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2563                 return token;
2564         }
2565
2566         if (klass->nested_in) {
2567                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2568                 /* get the typeref idx of the enclosing type */
2569                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2570                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2571         } else {
2572                 scope = resolution_scope_from_image (assembly, klass->image);
2573         }
2574         table = &assembly->tables [MONO_TABLE_TYPEREF];
2575         if (assembly->save) {
2576                 alloc_table (table, table->rows + 1);
2577                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2578                 values [MONO_TYPEREF_SCOPE] = scope;
2579                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2580                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2581         }
2582         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2583         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2584         table->next_idx ++;
2585         register_dyn_token (assembly, token, mono_class_get_ref_info (klass));
2586         return token;
2587 }
2588
2589 /*
2590  * Despite the name, we handle also TypeSpec (with the above helper).
2591  */
2592 static guint32
2593 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2594 {
2595         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2596 }
2597
2598 #ifndef DISABLE_REFLECTION_EMIT
2599 static guint32
2600 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2601 {
2602         MONO_REQ_GC_NEUTRAL_MODE;
2603
2604         MonoDynamicTable *table;
2605         guint32 *values;
2606         guint32 token, pclass;
2607
2608         switch (parent & MONO_TYPEDEFORREF_MASK) {
2609         case MONO_TYPEDEFORREF_TYPEREF:
2610                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2611                 break;
2612         case MONO_TYPEDEFORREF_TYPESPEC:
2613                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2614                 break;
2615         case MONO_TYPEDEFORREF_TYPEDEF:
2616                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2617                 break;
2618         default:
2619                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2620                 return 0;
2621         }
2622         /* extract the index */
2623         parent >>= MONO_TYPEDEFORREF_BITS;
2624
2625         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2626
2627         if (assembly->save) {
2628                 alloc_table (table, table->rows + 1);
2629                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2630                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2631                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2632                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2633         }
2634
2635         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2636         table->next_idx ++;
2637
2638         return token;
2639 }
2640
2641 /*
2642  * Insert a memberef row into the metadata: the token that point to the memberref
2643  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2644  * mono_image_get_fieldref_token()).
2645  * The sig param is an index to an already built signature.
2646  */
2647 static guint32
2648 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2649 {
2650         MONO_REQ_GC_NEUTRAL_MODE;
2651
2652         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2653         return mono_image_add_memberef_row (assembly, parent, name, sig);
2654 }
2655
2656
2657 static guint32
2658 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2659 {
2660         MONO_REQ_GC_NEUTRAL_MODE;
2661
2662         guint32 token;
2663         MonoMethodSignature *sig;
2664         
2665         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2666
2667         if (create_typespec) {
2668                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2669                 if (token)
2670                         return token;
2671         } 
2672
2673         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2674         if (token && !create_typespec)
2675                 return token;
2676
2677         g_assert (!method->is_inflated);
2678         if (!token) {
2679                 /*
2680                  * A methodref signature can't contain an unmanaged calling convention.
2681                  */
2682                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2683                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2684                         sig->call_convention = MONO_CALL_DEFAULT;
2685                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2686                         method->name,  method_encode_signature (assembly, sig));
2687                 g_free (sig);
2688                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2689         }
2690
2691         if (create_typespec) {
2692                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2693                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2694                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2695
2696                 if (assembly->save) {
2697                         guint32 *values;
2698
2699                         alloc_table (table, table->rows + 1);
2700                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2701                         values [MONO_METHODSPEC_METHOD] = token;
2702                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2703                 }
2704
2705                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2706                 table->next_idx ++;
2707                 /*methodspec and memberef tokens are diferent, */
2708                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2709                 return token;
2710         }
2711         return token;
2712 }
2713
2714 static guint32
2715 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2716 {
2717         guint32 token, parent, sig;
2718         ReflectionMethodBuilder rmb;
2719         char *name;
2720         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2721         
2722         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2723         if (token)
2724                 return token;
2725
2726         name = mono_string_to_utf8 (method->name);
2727         reflection_methodbuilder_from_method_builder (&rmb, method);
2728
2729         /*
2730          * A methodref signature can't contain an unmanaged calling convention.
2731          * Since some flags are encoded as part of call_conv, we need to check against it.
2732         */
2733         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2734                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2735
2736         sig = method_builder_encode_signature (assembly, &rmb);
2737
2738         if (tb->generic_params)
2739                 parent = create_generic_typespec (assembly, tb);
2740         else
2741                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2742
2743         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2744
2745         g_free (name);
2746         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2747         return token;
2748 }
2749
2750 static guint32
2751 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2752                                      const gchar *name, guint32 sig)
2753 {
2754         MonoDynamicTable *table;
2755         guint32 token;
2756         guint32 *values;
2757         
2758         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2759
2760         if (assembly->save) {
2761                 alloc_table (table, table->rows + 1);
2762                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2763                 values [MONO_MEMBERREF_CLASS] = original;
2764                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2765                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2766         }
2767
2768         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2769         table->next_idx ++;
2770
2771         return token;
2772 }
2773
2774 static guint32
2775 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2776 {
2777         SigBuffer buf;
2778         int i;
2779         guint32 nparams = mono_array_length (mb->generic_params);
2780         guint32 idx;
2781
2782         if (!assembly->save)
2783                 return 0;
2784
2785         sigbuffer_init (&buf, 32);
2786
2787         sigbuffer_add_value (&buf, 0xa);
2788         sigbuffer_add_value (&buf, nparams);
2789
2790         for (i = 0; i < nparams; i++) {
2791                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2792                 sigbuffer_add_value (&buf, i);
2793         }
2794
2795         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2796         sigbuffer_free (&buf);
2797         return idx;
2798 }
2799
2800 static guint32
2801 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2802 {
2803         MonoDynamicTable *table;
2804         guint32 *values;
2805         guint32 token, mtoken = 0;
2806
2807         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2808         if (token)
2809                 return token;
2810
2811         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2812
2813         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2814         switch (mono_metadata_token_table (mtoken)) {
2815         case MONO_TABLE_MEMBERREF:
2816                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2817                 break;
2818         case MONO_TABLE_METHOD:
2819                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2820                 break;
2821         default:
2822                 g_assert_not_reached ();
2823         }
2824
2825         if (assembly->save) {
2826                 alloc_table (table, table->rows + 1);
2827                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2828                 values [MONO_METHODSPEC_METHOD] = mtoken;
2829                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2830         }
2831
2832         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2833         table->next_idx ++;
2834
2835         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2836         return token;
2837 }
2838
2839 static guint32
2840 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2841 {
2842         guint32 token;
2843
2844         if (mb->generic_params && create_methodspec) 
2845                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2846
2847         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2848         if (token)
2849                 return token;
2850
2851         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2852         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2853         return token;
2854 }
2855
2856 static guint32
2857 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2858 {
2859         guint32 token, parent, sig;
2860         ReflectionMethodBuilder rmb;
2861         char *name;
2862         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2863         
2864         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2865         if (token)
2866                 return token;
2867
2868         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2869
2870         if (tb->generic_params)
2871                 parent = create_generic_typespec (assembly, tb);
2872         else
2873                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2874         
2875         name = mono_string_to_utf8 (rmb.name);
2876         sig = method_builder_encode_signature (assembly, &rmb);
2877
2878         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2879
2880         g_free (name);
2881         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2882         return token;
2883 }
2884 #endif
2885
2886 static gboolean
2887 is_field_on_inst (MonoClassField *field)
2888 {
2889         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2890 }
2891
2892 /*
2893  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2894  */
2895 static MonoType*
2896 get_field_on_inst_generic_type (MonoClassField *field)
2897 {
2898         MonoClass *class, *gtd;
2899         MonoDynamicGenericClass *dgclass;
2900         int field_index;
2901
2902         g_assert (is_field_on_inst (field));
2903
2904         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2905
2906         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2907                 field_index = field - dgclass->fields;
2908                 return dgclass->field_generic_types [field_index];              
2909         }
2910
2911         class = field->parent;
2912         gtd = class->generic_class->container_class;
2913
2914         if (field >= class->fields && field - class->fields < class->field.count) {
2915                 field_index = field - class->fields;
2916                 return gtd->fields [field_index].type;
2917         }
2918
2919         g_assert_not_reached ();
2920         return 0;
2921 }
2922
2923 #ifndef DISABLE_REFLECTION_EMIT
2924 static guint32
2925 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2926 {
2927         MonoType *type;
2928         guint32 token;
2929
2930         g_assert (field);
2931         g_assert (field->parent);
2932
2933         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2934         if (token)
2935                 return token;
2936
2937         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2938                 int index = field - field->parent->fields;
2939                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
2940         } else {
2941                 if (is_field_on_inst (field))
2942                         type = get_field_on_inst_generic_type (field);
2943                 else
2944                         type = mono_field_get_type (field);
2945         }
2946         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2947                                                                                         mono_field_get_name (field),
2948                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
2949         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2950         return token;
2951 }
2952
2953 static guint32
2954 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2955 {
2956         guint32 token;
2957         MonoClass *klass;
2958         MonoGenericClass *gclass;
2959         MonoType *type;
2960         char *name;
2961
2962         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2963         if (token)
2964                 return token;
2965         if (is_sre_field_builder (mono_object_class (f->fb))) {
2966                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2967                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2968                 klass = mono_class_from_mono_type (type);
2969                 gclass = type->data.generic_class;
2970                 g_assert (gclass->is_dynamic);
2971
2972                 name = mono_string_to_utf8 (fb->name);
2973                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
2974                                                                                                 field_encode_signature (assembly, fb));
2975                 g_free (name);          
2976         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2977                 guint32 sig;
2978                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2979
2980                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2981                 klass = mono_class_from_mono_type (type);
2982
2983                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2984                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2985         } else {
2986                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2987                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2988         }
2989
2990         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2991         return token;
2992 }
2993
2994 static guint32
2995 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2996 {
2997         guint32 sig, token;
2998         MonoClass *klass;
2999         MonoGenericClass *gclass;
3000         MonoType *type;
3001
3002         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3003
3004         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3005         if (token)
3006                 return token;
3007
3008         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3009                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3010                 ReflectionMethodBuilder rmb;
3011                 char *name;
3012
3013                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3014                 klass = mono_class_from_mono_type (type);
3015
3016                 gclass = type->data.generic_class;
3017                 g_assert (gclass->is_dynamic);
3018
3019                 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
3020
3021                 name = mono_string_to_utf8 (rmb.name);
3022
3023                 sig = method_builder_encode_signature (assembly, &rmb);
3024
3025                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3026                 g_free (name);
3027         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3028                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3029
3030                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3031                 klass = mono_class_from_mono_type (type);
3032
3033                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3034                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3035         } else {
3036                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3037                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3038         }
3039
3040
3041         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3042         return token;
3043 }
3044
3045 static MonoMethod*
3046 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
3047 {
3048         MonoError error;
3049         MonoClass *klass;
3050         MonoGenericContext tmp_context;
3051         MonoType **type_argv;
3052         MonoGenericInst *ginst;
3053         MonoMethod *method, *inflated;
3054         int count, i;
3055
3056         init_type_builder_generics ((MonoObject*)m->inst);
3057
3058         method = inflate_method (m->inst, (MonoObject*)m->mb);
3059
3060         klass = method->klass;
3061
3062         if (m->method_args == NULL)
3063                 return method;
3064
3065         if (method->is_inflated)
3066                 method = ((MonoMethodInflated *) method)->declaring;
3067
3068         count = mono_array_length (m->method_args);
3069
3070         type_argv = g_new0 (MonoType *, count);
3071         for (i = 0; i < count; i++) {
3072                 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
3073                 type_argv [i] = mono_reflection_type_get_handle (garg);
3074         }
3075         ginst = mono_metadata_get_generic_inst (count, type_argv);
3076         g_free (type_argv);
3077
3078         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3079         tmp_context.method_inst = ginst;
3080
3081         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
3082         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3083         return inflated;
3084 }
3085
3086 static guint32
3087 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
3088 {
3089         guint32 sig, token = 0;
3090         MonoType *type;
3091         MonoClass *klass;
3092
3093         if (m->method_args) {
3094                 MonoMethod *inflated;
3095
3096                 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
3097                 if (create_methodspec)
3098                         token = mono_image_get_methodspec_token (assembly, inflated);
3099                 else
3100                         token = mono_image_get_inflated_method_token (assembly, inflated);
3101                 return token;
3102         }
3103
3104         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3105         if (token)
3106                 return token;
3107
3108         if (is_sre_method_builder (mono_object_class (m->mb))) {
3109                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3110                 MonoGenericClass *gclass;
3111                 ReflectionMethodBuilder rmb;
3112                 char *name;
3113
3114                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3115                 klass = mono_class_from_mono_type (type);
3116                 gclass = type->data.generic_class;
3117                 g_assert (gclass->is_dynamic);
3118
3119                 reflection_methodbuilder_from_method_builder (&rmb, mb);
3120
3121                 name = mono_string_to_utf8 (rmb.name);
3122
3123                 sig = method_builder_encode_signature (assembly, &rmb);
3124
3125                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3126                 g_free (name);          
3127         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3128                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3129
3130                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3131                 klass = mono_class_from_mono_type (type);
3132
3133                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3134                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3135         } else {
3136                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3137                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3138         }
3139
3140         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3141         return token;
3142 }
3143
3144 static guint32
3145 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3146 {
3147         SigBuffer buf;
3148         int i;
3149         guint32 nparams = context->method_inst->type_argc;
3150         guint32 idx;
3151
3152         if (!assembly->save)
3153                 return 0;
3154
3155         sigbuffer_init (&buf, 32);
3156         /*
3157          * FIXME: vararg, explicit_this, differenc call_conv values...
3158          */
3159         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3160         sigbuffer_add_value (&buf, nparams);
3161
3162         for (i = 0; i < nparams; i++)
3163                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3164
3165         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3166         sigbuffer_free (&buf);
3167         return idx;
3168 }
3169
3170 static guint32
3171 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3172 {
3173         MonoDynamicTable *table;
3174         guint32 *values;
3175         guint32 token, mtoken = 0, sig;
3176         MonoMethodInflated *imethod;
3177         MonoMethod *declaring;
3178
3179         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3180
3181         g_assert (method->is_inflated);
3182         imethod = (MonoMethodInflated *) method;
3183         declaring = imethod->declaring;
3184
3185         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3186         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3187
3188         if (!mono_method_signature (declaring)->generic_param_count)
3189                 return mtoken;
3190
3191         switch (mono_metadata_token_table (mtoken)) {
3192         case MONO_TABLE_MEMBERREF:
3193                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3194                 break;
3195         case MONO_TABLE_METHOD:
3196                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3197                 break;
3198         default:
3199                 g_assert_not_reached ();
3200         }
3201
3202         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3203
3204         if (assembly->save) {
3205                 alloc_table (table, table->rows + 1);
3206                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3207                 values [MONO_METHODSPEC_METHOD] = mtoken;
3208                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3209         }
3210
3211         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3212         table->next_idx ++;
3213
3214         return token;
3215 }
3216
3217 static guint32
3218 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3219 {
3220         MonoMethodInflated *imethod;
3221         guint32 token;
3222         
3223         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3224         if (token)
3225                 return token;
3226
3227         g_assert (method->is_inflated);
3228         imethod = (MonoMethodInflated *) method;
3229
3230         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3231                 token = method_encode_methodspec (assembly, method);
3232         } else {
3233                 guint32 sig = method_encode_signature (
3234                         assembly, mono_method_signature (imethod->declaring));
3235                 token = mono_image_get_memberref_token (
3236                         assembly, &method->klass->byval_arg, method->name, sig);
3237         }
3238
3239         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3240         return token;
3241 }
3242
3243 static guint32
3244 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3245 {
3246         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3247         guint32 sig, token;
3248
3249         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3250         token = mono_image_get_memberref_token (
3251                 assembly, &m->klass->byval_arg, m->name, sig);
3252
3253         return token;
3254 }
3255
3256 static guint32
3257 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3258 {
3259         MonoDynamicTable *table;
3260         MonoClass *klass;
3261         MonoType *type;
3262         guint32 *values;
3263         guint32 token;
3264         SigBuffer buf;
3265         int count, i;
3266
3267         /*
3268          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3269          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3270          * Because of this, we must not insert it into the `typeref' hash table.
3271          */
3272         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3273         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3274         if (token)
3275                 return token;
3276
3277         sigbuffer_init (&buf, 32);
3278
3279         g_assert (tb->generic_params);
3280         klass = mono_class_from_mono_type (type);
3281
3282         if (tb->generic_container)
3283                 mono_reflection_create_generic_class (tb);
3284
3285         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3286         g_assert (klass->generic_container);
3287         sigbuffer_add_value (&buf, klass->byval_arg.type);
3288         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3289
3290         count = mono_array_length (tb->generic_params);
3291         sigbuffer_add_value (&buf, count);
3292         for (i = 0; i < count; i++) {
3293                 MonoReflectionGenericParam *gparam;
3294
3295                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3296
3297                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3298         }
3299
3300         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3301
3302         if (assembly->save) {
3303                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3304                 alloc_table (table, table->rows + 1);
3305                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3306                 values [MONO_TYPESPEC_SIGNATURE] = token;
3307         }
3308         sigbuffer_free (&buf);
3309
3310         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3311         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3312         table->next_idx ++;
3313         return token;
3314 }
3315
3316 /*
3317  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3318  */
3319 static MonoType*
3320 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3321 {
3322         int i, count, len, pos;
3323         MonoType *t;
3324
3325         count = 0;
3326         if (modreq)
3327                 count += mono_array_length (modreq);
3328         if (modopt)
3329                 count += mono_array_length (modopt);
3330
3331         if (count == 0)
3332                 return mono_metadata_type_dup (NULL, type);
3333
3334         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3335         t = g_malloc (len);
3336         memcpy (t, type, MONO_SIZEOF_TYPE);
3337
3338         t->num_mods = count;
3339         pos = 0;
3340         if (modreq) {
3341                 for (i = 0; i < mono_array_length (modreq); ++i) {
3342                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3343                         t->modifiers [pos].required = 1;
3344                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3345                         pos ++;
3346                 }
3347         }
3348         if (modopt) {
3349                 for (i = 0; i < mono_array_length (modopt); ++i) {
3350                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3351                         t->modifiers [pos].required = 0;
3352                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3353                         pos ++;
3354                 }
3355         }
3356
3357         return t;
3358 }
3359
3360 static void
3361 init_type_builder_generics (MonoObject *type)
3362 {
3363         MonoReflectionTypeBuilder *tb;
3364
3365         if (!is_sre_type_builder(mono_object_class (type)))
3366                 return;
3367         tb = (MonoReflectionTypeBuilder *)type;
3368
3369         if (tb && tb->generic_container)
3370                 mono_reflection_create_generic_class (tb);
3371 }
3372
3373 static guint32
3374 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3375 {
3376         MonoDynamicTable *table;
3377         MonoType *custom = NULL, *type;
3378         guint32 *values;
3379         guint32 token, pclass, parent, sig;
3380         gchar *name;
3381
3382         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3383         if (token)
3384                 return token;
3385
3386         /* FIXME: is this call necessary? */
3387         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3388         name = mono_string_to_utf8 (fb->name);
3389
3390         /*FIXME this is one more layer of ugliness due how types are created.*/
3391         init_type_builder_generics (fb->type);
3392
3393         /* fb->type does not include the custom modifiers */
3394         /* FIXME: We should do this in one place when a fieldbuilder is created */
3395         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3396         if (fb->modreq || fb->modopt)
3397                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3398
3399         sig = fieldref_encode_signature (assembly, NULL, type);
3400         g_free (custom);
3401
3402         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3403         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3404         
3405         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3406         parent >>= MONO_TYPEDEFORREF_BITS;
3407
3408         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3409
3410         if (assembly->save) {
3411                 alloc_table (table, table->rows + 1);
3412                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3413                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3414                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3415                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3416         }
3417
3418         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3419         table->next_idx ++;
3420         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3421         g_free (name);
3422         return token;
3423 }
3424
3425 static guint32
3426 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3427 {
3428         SigBuffer buf;
3429         guint32 nargs;
3430         guint32 i, idx;
3431
3432         if (!assembly->save)
3433                 return 0;
3434
3435         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3436         g_assert (helper->type == 2);
3437
3438         if (helper->arguments)
3439                 nargs = mono_array_length (helper->arguments);
3440         else
3441                 nargs = 0;
3442
3443         sigbuffer_init (&buf, 32);
3444
3445         /* Encode calling convention */
3446         /* Change Any to Standard */
3447         if ((helper->call_conv & 0x03) == 0x03)
3448                 helper->call_conv = 0x01;
3449         /* explicit_this implies has_this */
3450         if (helper->call_conv & 0x40)
3451                 helper->call_conv &= 0x20;
3452
3453         if (helper->call_conv == 0) { /* Unmanaged */
3454                 idx = helper->unmanaged_call_conv - 1;
3455         } else {
3456                 /* Managed */
3457                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3458                 if (helper->call_conv & 0x02) /* varargs */
3459                         idx += 0x05;
3460         }
3461
3462         sigbuffer_add_byte (&buf, idx);
3463         sigbuffer_add_value (&buf, nargs);
3464         encode_reflection_type (assembly, helper->return_type, &buf);
3465         for (i = 0; i < nargs; ++i) {
3466                 MonoArray *modreqs = NULL;
3467                 MonoArray *modopts = NULL;
3468                 MonoReflectionType *pt;
3469
3470                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3471                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3472                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3473                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3474
3475                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3476                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3477                 encode_reflection_type (assembly, pt, &buf);
3478         }
3479         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3480         sigbuffer_free (&buf);
3481
3482         return idx;
3483 }
3484
3485 static guint32 
3486 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3487 {
3488         guint32 idx;
3489         MonoDynamicTable *table;
3490         guint32 *values;
3491
3492         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3493         idx = table->next_idx ++;
3494         table->rows ++;
3495         alloc_table (table, table->rows);
3496         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3497
3498         values [MONO_STAND_ALONE_SIGNATURE] =
3499                 mono_reflection_encode_sighelper (assembly, helper);
3500
3501         return idx;
3502 }
3503
3504 static int
3505 reflection_cc_to_file (int call_conv) {
3506         switch (call_conv & 0x3) {
3507         case 0:
3508         case 1: return MONO_CALL_DEFAULT;
3509         case 2: return MONO_CALL_VARARG;
3510         default:
3511                 g_assert_not_reached ();
3512         }
3513         return 0;
3514 }
3515 #endif /* !DISABLE_REFLECTION_EMIT */
3516
3517 typedef struct {
3518         MonoType *parent;
3519         MonoMethodSignature *sig;
3520         char *name;
3521         guint32 token;
3522 } ArrayMethod;
3523
3524 #ifndef DISABLE_REFLECTION_EMIT
3525 static guint32
3526 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3527 {
3528         guint32 nparams, i;
3529         GList *tmp;
3530         char *name;
3531         MonoMethodSignature *sig;
3532         ArrayMethod *am;
3533         MonoType *mtype;
3534
3535         name = mono_string_to_utf8 (m->name);
3536         nparams = mono_array_length (m->parameters);
3537         sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3538         sig->hasthis = 1;
3539         sig->sentinelpos = -1;
3540         sig->call_convention = reflection_cc_to_file (m->call_conv);
3541         sig->param_count = nparams;
3542         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3543         mtype = mono_reflection_type_get_handle (m->parent);
3544         for (i = 0; i < nparams; ++i)
3545                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3546
3547         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3548                 am = tmp->data;
3549                 if (strcmp (name, am->name) == 0 && 
3550                                 mono_metadata_type_equal (am->parent, mtype) &&
3551                                 mono_metadata_signature_equal (am->sig, sig)) {
3552                         g_free (name);
3553                         g_free (sig);
3554                         m->table_idx = am->token & 0xffffff;
3555                         return am->token;
3556                 }
3557         }
3558         am = g_new0 (ArrayMethod, 1);
3559         am->name = name;
3560         am->sig = sig;
3561         am->parent = mtype;
3562         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3563                 method_encode_signature (assembly, sig));
3564         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3565         m->table_idx = am->token & 0xffffff;
3566         return am->token;
3567 }
3568
3569 /*
3570  * Insert into the metadata tables all the info about the TypeBuilder tb.
3571  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3572  */
3573 static void
3574 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3575 {
3576         MonoDynamicTable *table;
3577         guint *values;
3578         int i, is_object = 0, is_system = 0;
3579         char *n;
3580
3581         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3582         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3583         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3584         n = mono_string_to_utf8 (tb->name);
3585         if (strcmp (n, "Object") == 0)
3586                 is_object++;
3587         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3588         g_free (n);
3589         n = mono_string_to_utf8 (tb->nspace);
3590         if (strcmp (n, "System") == 0)
3591                 is_system++;
3592         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3593         g_free (n);
3594         if (tb->parent && !(is_system && is_object) && 
3595                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3596                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3597         } else {
3598                 values [MONO_TYPEDEF_EXTENDS] = 0;
3599         }
3600         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3601         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3602
3603         /*
3604          * if we have explicitlayout or sequentiallayouts, output data in the
3605          * ClassLayout table.
3606          */
3607         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3608                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3609                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3610                 table->rows++;
3611                 alloc_table (table, table->rows);
3612                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3613                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3614                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3615                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3616         }
3617
3618         /* handle interfaces */
3619         if (tb->interfaces) {
3620                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3621                 i = table->rows;
3622                 table->rows += mono_array_length (tb->interfaces);
3623                 alloc_table (table, table->rows);
3624                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3625                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3626                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3627                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3628                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3629                         values += MONO_INTERFACEIMPL_SIZE;
3630                 }
3631         }
3632
3633         /* handle fields */
3634         if (tb->fields) {
3635                 table = &assembly->tables [MONO_TABLE_FIELD];
3636                 table->rows += tb->num_fields;
3637                 alloc_table (table, table->rows);
3638                 for (i = 0; i < tb->num_fields; ++i)
3639                         mono_image_get_field_info (
3640                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3641         }
3642
3643         /* handle constructors */
3644         if (tb->ctors) {
3645                 table = &assembly->tables [MONO_TABLE_METHOD];
3646                 table->rows += mono_array_length (tb->ctors);
3647                 alloc_table (table, table->rows);
3648                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3649                         mono_image_get_ctor_info (domain,
3650                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3651         }
3652
3653         /* handle methods */
3654         if (tb->methods) {
3655                 table = &assembly->tables [MONO_TABLE_METHOD];
3656                 table->rows += tb->num_methods;
3657                 alloc_table (table, table->rows);
3658                 for (i = 0; i < tb->num_methods; ++i)
3659                         mono_image_get_method_info (
3660                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3661         }
3662
3663         /* Do the same with properties etc.. */
3664         if (tb->events && mono_array_length (tb->events)) {
3665                 table = &assembly->tables [MONO_TABLE_EVENT];
3666                 table->rows += mono_array_length (tb->events);
3667                 alloc_table (table, table->rows);
3668                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3669                 table->rows ++;
3670                 alloc_table (table, table->rows);
3671                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3672                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3673                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3674                 for (i = 0; i < mono_array_length (tb->events); ++i)
3675                         mono_image_get_event_info (
3676                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3677         }
3678         if (tb->properties && mono_array_length (tb->properties)) {
3679                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3680                 table->rows += mono_array_length (tb->properties);
3681                 alloc_table (table, table->rows);
3682                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3683                 table->rows ++;
3684                 alloc_table (table, table->rows);
3685                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3686                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3687                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3688                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3689                         mono_image_get_property_info (
3690                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3691         }
3692
3693         /* handle generic parameters */
3694         if (tb->generic_params) {
3695                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3696                 table->rows += mono_array_length (tb->generic_params);
3697                 alloc_table (table, table->rows);
3698                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3699                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3700
3701                         mono_image_get_generic_param_info (
3702                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3703                 }
3704         }
3705
3706         mono_image_add_decl_security (assembly, 
3707                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3708
3709         if (tb->subtypes) {
3710                 MonoDynamicTable *ntable;
3711                 
3712                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3713                 ntable->rows += mono_array_length (tb->subtypes);
3714                 alloc_table (ntable, ntable->rows);
3715                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3716
3717                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3718                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3719
3720                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3721                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3722                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3723                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3724                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3725                                 ntable->next_idx, ntable->rows);*/
3726                         values += MONO_NESTED_CLASS_SIZE;
3727                         ntable->next_idx++;
3728                 }
3729         }
3730 }
3731 #endif
3732
3733 static void
3734 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3735 {
3736         int i;
3737
3738         mono_ptr_array_append (*types, type);
3739
3740         if (!type->subtypes)
3741                 return;
3742
3743         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3744                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3745                 collect_types (types, subtype);
3746         }
3747 }
3748
3749 static gint
3750 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3751 {
3752         if ((*type1)->table_idx < (*type2)->table_idx)
3753                 return -1;
3754         else
3755                 if ((*type1)->table_idx > (*type2)->table_idx)
3756                         return 1;
3757         else
3758                 return 0;
3759 }
3760
3761 static void
3762 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3763         int i;
3764
3765         if (!pinfo)
3766                 return;
3767         for (i = 0; i < mono_array_length (pinfo); ++i) {
3768                 MonoReflectionParamBuilder *pb;
3769                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3770                 if (!pb)
3771                         continue;
3772                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3773         }
3774 }
3775
3776 static void
3777 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3778         int i;
3779         
3780         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3781         if (tb->fields) {
3782                 for (i = 0; i < tb->num_fields; ++i) {
3783                         MonoReflectionFieldBuilder* fb;
3784                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3785                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3786                 }
3787         }
3788         if (tb->events) {
3789                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3790                         MonoReflectionEventBuilder* eb;
3791                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3792                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3793                 }
3794         }
3795         if (tb->properties) {
3796                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3797                         MonoReflectionPropertyBuilder* pb;
3798                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3799                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3800                 }
3801         }
3802         if (tb->ctors) {
3803                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3804                         MonoReflectionCtorBuilder* cb;
3805                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3806                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3807                         params_add_cattrs (assembly, cb->pinfo);
3808                 }
3809         }
3810
3811         if (tb->methods) {
3812                 for (i = 0; i < tb->num_methods; ++i) {
3813                         MonoReflectionMethodBuilder* mb;
3814                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3815                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3816                         params_add_cattrs (assembly, mb->pinfo);
3817                 }
3818         }
3819
3820         if (tb->subtypes) {
3821                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3822                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3823         }
3824 }
3825
3826 static void
3827 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3828 {
3829         int i;
3830         
3831         mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3832
3833         if (moduleb->global_methods) {
3834                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3835                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3836                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3837                         params_add_cattrs (assembly, mb->pinfo);
3838                 }
3839         }
3840
3841         if (moduleb->global_fields) {
3842                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3843                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3844                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3845                 }
3846         }
3847         
3848         if (moduleb->types) {
3849                 for (i = 0; i < moduleb->num_types; ++i)
3850                         type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3851         }
3852 }
3853
3854 static void
3855 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3856 {
3857         MonoDynamicTable *table;
3858         guint32 *values;
3859         char blob_size [6];
3860         guchar hash [20];
3861         char *b = blob_size;
3862         char *dir, *path;
3863
3864         table = &assembly->tables [MONO_TABLE_FILE];
3865         table->rows++;
3866         alloc_table (table, table->rows);
3867         values = table->values + table->next_idx * MONO_FILE_SIZE;
3868         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3869         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3870         if (image_is_dynamic (module->image)) {
3871                 /* This depends on the fact that the main module is emitted last */
3872                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3873                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3874         } else {
3875                 dir = NULL;
3876                 path = g_strdup (module->image->name);
3877         }
3878         mono_sha1_get_digest_from_file (path, hash);
3879         g_free (dir);
3880         g_free (path);
3881         mono_metadata_encode_value (20, b, &b);
3882         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3883         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3884         table->next_idx ++;
3885 }
3886
3887 static void
3888 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3889 {
3890         MonoDynamicTable *table;
3891         int i;
3892
3893         table = &assembly->tables [MONO_TABLE_MODULE];
3894         mb->table_idx = table->next_idx ++;
3895         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3896         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3897         i /= 16;
3898         ++i;
3899         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3900         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3901         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3902         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3903 }
3904
3905 static guint32
3906 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3907         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3908 {
3909         MonoDynamicTable *table;
3910         guint32 *values;
3911         guint32 visib, res;
3912
3913         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3914         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3915                 return 0;
3916
3917         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3918         table->rows++;
3919         alloc_table (table, table->rows);
3920         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3921
3922         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3923         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3924         if (klass->nested_in)
3925                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3926         else
3927                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3928         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3929         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3930
3931         res = table->next_idx;
3932
3933         table->next_idx ++;
3934
3935         /* Emit nested types */
3936         if (klass->ext && klass->ext->nested_classes) {
3937                 GList *tmp;
3938
3939                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3940                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3941         }
3942
3943         return res;
3944 }
3945
3946 static void
3947 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3948         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3949 {
3950         MonoClass *klass;
3951         guint32 idx, i;
3952
3953         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3954
3955         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3956
3957         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3958                                                                                                    parent_index, assembly);
3959
3960         /* 
3961          * Emit nested types
3962          * We need to do this ourselves since klass->nested_classes is not set up.
3963          */
3964         if (tb->subtypes) {
3965                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3966                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3967         }
3968 }
3969
3970 static void
3971 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3972         guint32 module_index, MonoDynamicImage *assembly)
3973 {
3974         MonoImage *image = module->image;
3975         MonoTableInfo  *t;
3976         guint32 i;
3977
3978         t = &image->tables [MONO_TABLE_TYPEDEF];
3979
3980         for (i = 0; i < t->rows; ++i) {
3981                 MonoError error;
3982                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
3983                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
3984
3985                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3986                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3987         }
3988 }
3989
3990 static void
3991 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3992 {
3993         MonoDynamicTable *table;
3994         guint32 *values;
3995         guint32 scope, scope_idx, impl, current_idx;
3996         gboolean forwarder = TRUE;
3997         gpointer iter = NULL;
3998         MonoClass *nested;
3999
4000         if (klass->nested_in) {
4001                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4002                 forwarder = FALSE;
4003         } else {
4004                 scope = resolution_scope_from_image (assembly, klass->image);
4005                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4006                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4007                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4008         }
4009
4010         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4011
4012         table->rows++;
4013         alloc_table (table, table->rows);
4014         current_idx = table->next_idx;
4015         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4016
4017         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4018         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4019         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4020         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4021         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4022
4023         table->next_idx++;
4024
4025         while ((nested = mono_class_get_nested_types (klass, &iter)))
4026                 add_exported_type (assemblyb, assembly, nested, current_idx);
4027 }
4028
4029 static void
4030 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4031 {
4032         MonoClass *klass;
4033         int i;
4034
4035         if (!assemblyb->type_forwarders)
4036                 return;
4037
4038         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4039                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4040                 MonoType *type;
4041                 if (!t)
4042                         continue;
4043
4044                 type = mono_reflection_type_get_handle (t);
4045                 g_assert (type);
4046
4047                 klass = mono_class_from_mono_type (type);
4048
4049                 add_exported_type (assemblyb, assembly, klass, 0);
4050         }
4051 }
4052
4053 #define align_pointer(base,p)\
4054         do {\
4055                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4056                 if (__diff & 3)\
4057                         (p) += 4 - (__diff & 3);\
4058         } while (0)
4059
4060 static int
4061 compare_constants (const void *a, const void *b)
4062 {
4063         const guint32 *a_values = a;
4064         const guint32 *b_values = b;
4065         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4066 }
4067
4068 static int
4069 compare_semantics (const void *a, const void *b)
4070 {
4071         const guint32 *a_values = a;
4072         const guint32 *b_values = b;
4073         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4074         if (assoc)
4075                 return assoc;
4076         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4077 }
4078
4079 static int
4080 compare_custom_attrs (const void *a, const void *b)
4081 {
4082         const guint32 *a_values = a;
4083         const guint32 *b_values = b;
4084
4085         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4086 }
4087
4088 static int
4089 compare_field_marshal (const void *a, const void *b)
4090 {
4091         const guint32 *a_values = a;
4092         const guint32 *b_values = b;
4093
4094         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4095 }
4096
4097 static int
4098 compare_nested (const void *a, const void *b)
4099 {
4100         const guint32 *a_values = a;
4101         const guint32 *b_values = b;
4102
4103         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4104 }
4105
4106 static int
4107 compare_genericparam (const void *a, const void *b)
4108 {
4109         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4110         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4111
4112         if ((*b_entry)->owner == (*a_entry)->owner)
4113                 return 
4114                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4115                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4116         else
4117                 return (*a_entry)->owner - (*b_entry)->owner;
4118 }
4119
4120 static int
4121 compare_declsecurity_attrs (const void *a, const void *b)
4122 {
4123         const guint32 *a_values = a;
4124         const guint32 *b_values = b;
4125
4126         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4127 }
4128
4129 static int
4130 compare_interface_impl (const void *a, const void *b)
4131 {
4132         const guint32 *a_values = a;
4133         const guint32 *b_values = b;
4134
4135         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4136         if (klass)
4137                 return klass;
4138
4139         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4140 }
4141
4142 static void
4143 pad_heap (MonoDynamicStream *sh)
4144 {
4145         if (sh->index & 3) {
4146                 int sz = 4 - (sh->index & 3);
4147                 memset (sh->data + sh->index, 0, sz);
4148                 sh->index += sz;
4149         }
4150 }
4151
4152 struct StreamDesc {
4153         const char *name;
4154         MonoDynamicStream *stream;
4155 };
4156
4157 /*
4158  * build_compressed_metadata() fills in the blob of data that represents the 
4159  * raw metadata as it will be saved in the PE file. The five streams are output 
4160  * and the metadata tables are comnpressed from the guint32 array representation, 
4161  * to the compressed on-disk format.
4162  */
4163 static void
4164 build_compressed_metadata (MonoDynamicImage *assembly)
4165 {
4166         MonoDynamicTable *table;
4167         int i;
4168         guint64 valid_mask = 0;
4169         guint64 sorted_mask;
4170         guint32 heapt_size = 0;
4171         guint32 meta_size = 256; /* allow for header and other stuff */
4172         guint32 table_offset;
4173         guint32 ntables = 0;
4174         guint64 *int64val;
4175         guint32 *int32val;
4176         guint16 *int16val;
4177         MonoImage *meta;
4178         unsigned char *p;
4179         struct StreamDesc stream_desc [5];
4180
4181         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4182         for (i = 0; i < assembly->gen_params->len; i++){
4183                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
4184                 write_generic_param_entry (assembly, entry);
4185         }
4186
4187         stream_desc [0].name  = "#~";
4188         stream_desc [0].stream = &assembly->tstream;
4189         stream_desc [1].name  = "#Strings";
4190         stream_desc [1].stream = &assembly->sheap;
4191         stream_desc [2].name  = "#US";
4192         stream_desc [2].stream = &assembly->us;
4193         stream_desc [3].name  = "#Blob";
4194         stream_desc [3].stream = &assembly->blob;
4195         stream_desc [4].name  = "#GUID";
4196         stream_desc [4].stream = &assembly->guid;
4197         
4198         /* tables that are sorted */
4199         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4200                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4201                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4202                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4203                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4204                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4205                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4206         
4207         /* Compute table sizes */
4208         /* the MonoImage has already been created in mono_image_basic_init() */
4209         meta = &assembly->image;
4210
4211         /* sizes should be multiple of 4 */
4212         pad_heap (&assembly->blob);
4213         pad_heap (&assembly->guid);
4214         pad_heap (&assembly->sheap);
4215         pad_heap (&assembly->us);
4216
4217         /* Setup the info used by compute_sizes () */
4218         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4219         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4220         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4221
4222         meta_size += assembly->blob.index;
4223         meta_size += assembly->guid.index;
4224         meta_size += assembly->sheap.index;
4225         meta_size += assembly->us.index;
4226
4227         for (i=0; i < MONO_TABLE_NUM; ++i)
4228                 meta->tables [i].rows = assembly->tables [i].rows;
4229         
4230         for (i = 0; i < MONO_TABLE_NUM; i++){
4231                 if (meta->tables [i].rows == 0)
4232                         continue;
4233                 valid_mask |= (guint64)1 << i;
4234                 ntables ++;
4235                 meta->tables [i].row_size = mono_metadata_compute_size (
4236                         meta, i, &meta->tables [i].size_bitfield);
4237                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4238         }
4239         heapt_size += 24; /* #~ header size */
4240         heapt_size += ntables * 4;
4241         /* make multiple of 4 */
4242         heapt_size += 3;
4243         heapt_size &= ~3;
4244         meta_size += heapt_size;
4245         meta->raw_metadata = g_malloc0 (meta_size);
4246         p = (unsigned char*)meta->raw_metadata;
4247         /* the metadata signature */
4248         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4249         /* version numbers and 4 bytes reserved */
4250         int16val = (guint16*)p;
4251         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4252         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4253         p += 8;
4254         /* version string */
4255         int32val = (guint32*)p;
4256         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4257         p += 4;
4258         memcpy (p, meta->version, strlen (meta->version));
4259         p += GUINT32_FROM_LE (*int32val);
4260         align_pointer (meta->raw_metadata, p);
4261         int16val = (guint16*)p;
4262         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4263         *int16val = GUINT16_TO_LE (5); /* number of streams */
4264         p += 4;
4265
4266         /*
4267          * write the stream info.
4268          */
4269         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4270         table_offset += 3; table_offset &= ~3;
4271
4272         assembly->tstream.index = heapt_size;
4273         for (i = 0; i < 5; ++i) {
4274                 int32val = (guint32*)p;
4275                 stream_desc [i].stream->offset = table_offset;
4276                 *int32val++ = GUINT32_TO_LE (table_offset);
4277                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4278                 table_offset += GUINT32_FROM_LE (*int32val);
4279                 table_offset += 3; table_offset &= ~3;
4280                 p += 8;
4281                 strcpy ((char*)p, stream_desc [i].name);
4282                 p += strlen (stream_desc [i].name) + 1;
4283                 align_pointer (meta->raw_metadata, p);
4284         }
4285         /* 
4286          * now copy the data, the table stream header and contents goes first.
4287          */
4288         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4289         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4290         int32val = (guint32*)p;
4291         *int32val = GUINT32_TO_LE (0); /* reserved */
4292         p += 4;
4293
4294         *p++ = 2; /* version */
4295         *p++ = 0;
4296
4297         if (meta->idx_string_wide)
4298                 *p |= 0x01;
4299         if (meta->idx_guid_wide)
4300                 *p |= 0x02;
4301         if (meta->idx_blob_wide)
4302                 *p |= 0x04;
4303         ++p;
4304         *p++ = 1; /* reserved */
4305         int64val = (guint64*)p;
4306         *int64val++ = GUINT64_TO_LE (valid_mask);
4307         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4308         p += 16;
4309         int32val = (guint32*)p;
4310         for (i = 0; i < MONO_TABLE_NUM; i++){
4311                 if (meta->tables [i].rows == 0)
4312                         continue;
4313                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4314         }
4315         p = (unsigned char*)int32val;
4316
4317         /* sort the tables that still need sorting */
4318         table = &assembly->tables [MONO_TABLE_CONSTANT];
4319         if (table->rows)
4320                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4321         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4322         if (table->rows)
4323                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4324         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4325         if (table->rows)
4326                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4327         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4328         if (table->rows)
4329                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4330         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4331         if (table->rows)
4332                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4333         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4334         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4335         if (table->rows)
4336                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4337         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4338         if (table->rows)
4339                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4340
4341         /* compress the tables */
4342         for (i = 0; i < MONO_TABLE_NUM; i++){
4343                 int row, col;
4344                 guint32 *values;
4345                 guint32 bitfield = meta->tables [i].size_bitfield;
4346                 if (!meta->tables [i].rows)
4347                         continue;
4348                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4349                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4350                 meta->tables [i].base = (char*)p;
4351                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4352                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4353                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4354                                 switch (mono_metadata_table_size (bitfield, col)) {
4355                                 case 1:
4356                                         *p++ = values [col];
4357                                         break;
4358                                 case 2:
4359                                         *p++ = values [col] & 0xff;
4360                                         *p++ = (values [col] >> 8) & 0xff;
4361                                         break;
4362                                 case 4:
4363                                         *p++ = values [col] & 0xff;
4364                                         *p++ = (values [col] >> 8) & 0xff;
4365                                         *p++ = (values [col] >> 16) & 0xff;
4366                                         *p++ = (values [col] >> 24) & 0xff;
4367                                         break;
4368                                 default:
4369                                         g_assert_not_reached ();
4370                                 }
4371                         }
4372                 }
4373                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4374         }
4375         
4376         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4377         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4378         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4379         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4380         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4381
4382         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4383 }
4384
4385 /*
4386  * Some tables in metadata need to be sorted according to some criteria, but
4387  * when methods and fields are first created with reflection, they may be assigned a token
4388  * that doesn't correspond to the final token they will get assigned after the sorting.
4389  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4390  * with the reflection objects that represent them. Once all the tables are set up, the 
4391  * reflection objects will contains the correct table index. fixup_method() will fixup the
4392  * tokens for the method with ILGenerator @ilgen.
4393  */
4394 static void
4395 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4396 {
4397         guint32 code_idx = GPOINTER_TO_UINT (value);
4398         MonoReflectionILTokenInfo *iltoken;
4399         MonoReflectionFieldBuilder *field;
4400         MonoReflectionCtorBuilder *ctor;
4401         MonoReflectionMethodBuilder *method;
4402         MonoReflectionTypeBuilder *tb;
4403         MonoReflectionArrayMethod *am;
4404         guint32 i, idx = 0;
4405         unsigned char *target;
4406
4407         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4408                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4409                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4410                 switch (target [3]) {
4411                 case MONO_TABLE_FIELD:
4412                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4413                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4414                                 idx = field->table_idx;
4415                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4416                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4417                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4418                         } else {
4419                                 g_assert_not_reached ();
4420                         }
4421                         break;
4422                 case MONO_TABLE_METHOD:
4423                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4424                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4425                                 idx = method->table_idx;
4426                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4427                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4428                                 idx = ctor->table_idx;
4429                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4430                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4431                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4432                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4433                         } else {
4434                                 g_assert_not_reached ();
4435                         }
4436                         break;
4437                 case MONO_TABLE_TYPEDEF:
4438                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4439                                 g_assert_not_reached ();
4440                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4441                         idx = tb->table_idx;
4442                         break;
4443                 case MONO_TABLE_MEMBERREF:
4444                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4445                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4446                                 idx = am->table_idx;
4447                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4448                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4449                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4450                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4451                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4452                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4453                                 continue;
4454                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4455                                 continue;
4456                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4457                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4458                                 g_assert (is_field_on_inst (f));
4459                                 continue;
4460                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4461                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4462                                 continue;
4463                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4464                                 continue;
4465                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4466                                 continue;
4467                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4468                                 continue;
4469                         } else {
4470                                 g_assert_not_reached ();
4471                         }
4472                         break;
4473                 case MONO_TABLE_METHODSPEC:
4474                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4475                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4476                                 g_assert (mono_method_signature (m)->generic_param_count);
4477                                 continue;
4478                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4479                                 continue;
4480                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4481                                 continue;
4482                         } else {
4483                                 g_assert_not_reached ();
4484                         }
4485                         break;
4486                 default:
4487                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4488                 }
4489                 target [0] = idx & 0xff;
4490                 target [1] = (idx >> 8) & 0xff;
4491                 target [2] = (idx >> 16) & 0xff;
4492         }
4493 }
4494
4495 /*
4496  * fixup_cattrs:
4497  *
4498  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4499  * value is not known when the table is emitted.
4500  */
4501 static void
4502 fixup_cattrs (MonoDynamicImage *assembly)
4503 {
4504         MonoDynamicTable *table;
4505         guint32 *values;
4506         guint32 type, i, idx, token;
4507         MonoObject *ctor;
4508
4509         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4510
4511         for (i = 0; i < table->rows; ++i) {
4512                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4513
4514                 type = values [MONO_CUSTOM_ATTR_TYPE];
4515                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4516                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4517                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4518                         ctor = mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4519                         g_assert (ctor);
4520
4521                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4522                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4523                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4524                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4525                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4526                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4527                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4528                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4529                         }
4530                 }
4531         }
4532 }
4533
4534 static void
4535 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4536 {
4537         MonoDynamicTable *table;
4538         guint32 *values;
4539
4540         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4541         table->rows++;
4542         alloc_table (table, table->rows);
4543         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4544         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4545         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4546         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4547         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4548         table->next_idx++;
4549 }
4550
4551 static void
4552 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4553 {
4554         MonoDynamicTable *table;
4555         guint32 *values;
4556         char blob_size [6];
4557         guchar hash [20];
4558         char *b = blob_size;
4559         char *name, *sname;
4560         guint32 idx, offset;
4561
4562         if (rsrc->filename) {
4563                 name = mono_string_to_utf8 (rsrc->filename);
4564                 sname = g_path_get_basename (name);
4565         
4566                 table = &assembly->tables [MONO_TABLE_FILE];
4567                 table->rows++;
4568                 alloc_table (table, table->rows);
4569                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4570                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4571                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4572                 g_free (sname);
4573
4574                 mono_sha1_get_digest_from_file (name, hash);
4575                 mono_metadata_encode_value (20, b, &b);
4576                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4577                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4578                 g_free (name);
4579                 idx = table->next_idx++;
4580                 rsrc->offset = 0;
4581                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4582         } else {
4583                 char sizebuf [4];
4584                 char *data;
4585                 guint len;
4586                 if (rsrc->data) {
4587                         data = mono_array_addr (rsrc->data, char, 0);
4588                         len = mono_array_length (rsrc->data);
4589                 } else {
4590                         data = NULL;
4591                         len = 0;
4592                 }
4593                 offset = len;
4594                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4595                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4596                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4597                 mono_image_add_stream_data (&assembly->resources, data, len);
4598
4599                 if (!mb->is_main)
4600                         /* 
4601                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4602                          * the main module, but that needs to reference the FILE table
4603                          * which isn't emitted yet.
4604                          */
4605                         return;
4606                 else
4607                         idx = 0;
4608         }
4609
4610         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4611 }
4612
4613 static void
4614 set_version_from_string (MonoString *version, guint32 *values)
4615 {
4616         gchar *ver, *p, *str;
4617         guint32 i;
4618         
4619         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4620         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4621         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4622         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4623         if (!version)
4624                 return;
4625         ver = str = mono_string_to_utf8 (version);
4626         for (i = 0; i < 4; ++i) {
4627                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4628                 switch (*p) {
4629                 case '.':
4630                         p++;
4631                         break;
4632                 case '*':
4633                         /* handle Revision and Build */
4634                         p++;
4635                         break;
4636                 }
4637                 ver = p;
4638         }
4639         g_free (str);
4640 }
4641
4642 static guint32
4643 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4644         gsize len;
4645         guint32 token = 0;
4646         char blob_size [6];
4647         char *b = blob_size;
4648
4649         if (!pkey)
4650                 return token;
4651
4652         len = mono_array_length (pkey);
4653         mono_metadata_encode_value (len, b, &b);
4654         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4655         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4656
4657         assembly->public_key = g_malloc (len);
4658         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4659         assembly->public_key_len = len;
4660
4661         /* Special case: check for ECMA key (16 bytes) */
4662         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4663                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4664                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4665         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4666                 /* minimum key size (in 2.0) is 384 bits */
4667                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4668         } else {
4669                 /* FIXME - verifier */
4670                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4671                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4672         }
4673         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4674
4675         return token;
4676 }
4677
4678 static void
4679 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4680 {
4681         MonoDynamicTable *table;
4682         MonoDynamicImage *assembly;
4683         MonoReflectionAssemblyBuilder *assemblyb;
4684         MonoDomain *domain;
4685         guint32 *values;
4686         int i;
4687         guint32 module_index;
4688
4689         assemblyb = moduleb->assemblyb;
4690         assembly = moduleb->dynamic_image;
4691         domain = mono_object_domain (assemblyb);
4692
4693         /* Emit ASSEMBLY table */
4694         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4695         alloc_table (table, 1);
4696         values = table->values + MONO_ASSEMBLY_SIZE;
4697         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4698         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4699         if (assemblyb->culture) {
4700                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4701         } else {
4702                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4703         }
4704         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4705         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4706         set_version_from_string (assemblyb->version, values);
4707
4708         /* Emit FILE + EXPORTED_TYPE table */
4709         module_index = 0;
4710         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4711                 int j;
4712                 MonoReflectionModuleBuilder *file_module = 
4713                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4714                 if (file_module != moduleb) {
4715                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4716                         module_index ++;
4717                         if (file_module->types) {
4718                                 for (j = 0; j < file_module->num_types; ++j) {
4719                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4720                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4721                                 }
4722                         }
4723                 }
4724         }
4725         if (assemblyb->loaded_modules) {
4726                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4727                         MonoReflectionModule *file_module = 
4728                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4729                         mono_image_fill_file_table (domain, file_module, assembly);
4730                         module_index ++;
4731                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4732                 }
4733         }
4734         if (assemblyb->type_forwarders)
4735                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4736
4737         /* Emit MANIFESTRESOURCE table */
4738         module_index = 0;
4739         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4740                 int j;
4741                 MonoReflectionModuleBuilder *file_module = 
4742                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4743                 /* The table for the main module is emitted later */
4744                 if (file_module != moduleb) {
4745                         module_index ++;
4746                         if (file_module->resources) {
4747                                 int len = mono_array_length (file_module->resources);
4748                                 for (j = 0; j < len; ++j) {
4749                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4750                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4751                                 }
4752                         }
4753                 }
4754         }               
4755 }
4756
4757 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4758
4759 /*
4760  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4761  * for the modulebuilder @moduleb.
4762  * At the end of the process, method and field tokens are fixed up and the 
4763  * on-disk compressed metadata representation is created.
4764  */
4765 void
4766 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4767 {
4768         MonoDynamicTable *table;
4769         MonoDynamicImage *assembly;
4770         MonoReflectionAssemblyBuilder *assemblyb;
4771         MonoDomain *domain;
4772         MonoPtrArray types;
4773         guint32 *values;
4774         int i, j;
4775
4776         assemblyb = moduleb->assemblyb;
4777         assembly = moduleb->dynamic_image;
4778         domain = mono_object_domain (assemblyb);
4779
4780         if (assembly->text_rva)
4781                 return;
4782
4783         assembly->text_rva = START_TEXT_RVA;
4784
4785         if (moduleb->is_main) {
4786                 mono_image_emit_manifest (moduleb);
4787         }
4788
4789         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4790         table->rows = 1; /* .<Module> */
4791         table->next_idx++;
4792         alloc_table (table, table->rows);
4793         /*
4794          * Set the first entry.
4795          */
4796         values = table->values + table->columns;
4797         values [MONO_TYPEDEF_FLAGS] = 0;
4798         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4799         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4800         values [MONO_TYPEDEF_EXTENDS] = 0;
4801         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4802         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4803
4804         /* 
4805          * handle global methods 
4806          * FIXME: test what to do when global methods are defined in multiple modules.
4807          */
4808         if (moduleb->global_methods) {
4809                 table = &assembly->tables [MONO_TABLE_METHOD];
4810                 table->rows += mono_array_length (moduleb->global_methods);
4811                 alloc_table (table, table->rows);
4812                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4813                         mono_image_get_method_info (
4814                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4815         }
4816         if (moduleb->global_fields) {
4817                 table = &assembly->tables [MONO_TABLE_FIELD];
4818                 table->rows += mono_array_length (moduleb->global_fields);
4819                 alloc_table (table, table->rows);
4820                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4821                         mono_image_get_field_info (
4822                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4823         }
4824
4825         table = &assembly->tables [MONO_TABLE_MODULE];
4826         alloc_table (table, 1);
4827         mono_image_fill_module_table (domain, moduleb, assembly);
4828
4829         /* Collect all types into a list sorted by their table_idx */
4830         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
4831
4832         if (moduleb->types)
4833                 for (i = 0; i < moduleb->num_types; ++i) {
4834                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4835                         collect_types (&types, type);
4836                 }
4837
4838         mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4839         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4840         table->rows += mono_ptr_array_size (types);
4841         alloc_table (table, table->rows);
4842
4843         /*
4844          * Emit type names + namespaces at one place inside the string heap,
4845          * so load_class_names () needs to touch fewer pages.
4846          */
4847         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4848                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4849                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4850         }
4851         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4852                 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4853                 string_heap_insert_mstring (&assembly->sheap, tb->name);
4854         }
4855
4856         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4857                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4858                 mono_image_get_type_info (domain, type, assembly);
4859         }
4860
4861         /* 
4862          * table->rows is already set above and in mono_image_fill_module_table.
4863          */
4864         /* add all the custom attributes at the end, once all the indexes are stable */
4865         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4866
4867         /* CAS assembly permissions */
4868         if (assemblyb->permissions_minimum)
4869                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4870         if (assemblyb->permissions_optional)
4871                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4872         if (assemblyb->permissions_refused)
4873                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4874
4875         module_add_cattrs (assembly, moduleb);
4876
4877         /* fixup tokens */
4878         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4879
4880         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
4881          * the final tokens and don't need another fixup pass. */
4882
4883         if (moduleb->global_methods) {
4884                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4885                         MonoReflectionMethodBuilder *mb = mono_array_get (
4886                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4887                         mono_image_add_methodimpl (assembly, mb);
4888                 }
4889         }
4890
4891         for (i = 0; i < mono_ptr_array_size (types); ++i) {
4892                 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4893                 if (type->methods) {
4894                         for (j = 0; j < type->num_methods; ++j) {
4895                                 MonoReflectionMethodBuilder *mb = mono_array_get (
4896                                         type->methods, MonoReflectionMethodBuilder*, j);
4897
4898                                 mono_image_add_methodimpl (assembly, mb);
4899                         }
4900                 }
4901         }
4902
4903         mono_ptr_array_destroy (types);
4904
4905         fixup_cattrs (assembly);
4906 }
4907
4908 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4909
4910 void
4911 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4912 {
4913         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4914 }
4915
4916 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4917
4918
4919 typedef struct {
4920         guint32 import_lookup_table;
4921         guint32 timestamp;
4922         guint32 forwarder;
4923         guint32 name_rva;
4924         guint32 import_address_table_rva;
4925 } MonoIDT;
4926
4927 typedef struct {
4928         guint32 name_rva;
4929         guint32 flags;
4930 } MonoILT;
4931
4932 #ifndef DISABLE_REFLECTION_EMIT
4933
4934 /*
4935  * mono_image_insert_string:
4936  * @module: module builder object
4937  * @str: a string
4938  *
4939  * Insert @str into the user string stream of @module.
4940  */
4941 guint32
4942 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4943 {
4944         MonoDynamicImage *assembly;
4945         guint32 idx;
4946         char buf [16];
4947         char *b = buf;
4948         
4949         if (!module->dynamic_image)
4950                 mono_image_module_basic_init (module);
4951
4952         assembly = module->dynamic_image;
4953         
4954         if (assembly->save) {
4955                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4956                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4957 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4958         {
4959                 char *swapped = g_malloc (2 * mono_string_length (str));
4960                 const char *p = (const char*)mono_string_chars (str);
4961
4962                 swap_with_size (swapped, p, 2, mono_string_length (str));
4963                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4964                 g_free (swapped);
4965         }
4966 #else
4967                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4968 #endif
4969                 mono_image_add_stream_data (&assembly->us, "", 1);
4970         } else {
4971                 idx = assembly->us.index ++;
4972         }
4973
4974         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
4975
4976         return MONO_TOKEN_STRING | idx;
4977 }
4978
4979 guint32
4980 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4981 {
4982         MonoClass *klass;
4983         guint32 token = 0;
4984         MonoMethodSignature *sig;
4985
4986         klass = obj->vtable->klass;
4987         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
4988                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4989                 MonoMethodSignature *old;
4990                 guint32 sig_token, parent;
4991                 int nargs, i;
4992
4993                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4994
4995                 nargs = mono_array_length (opt_param_types);
4996                 old = mono_method_signature (method);
4997                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4998
4999                 sig->hasthis = old->hasthis;
5000                 sig->explicit_this = old->explicit_this;
5001                 sig->call_convention = old->call_convention;
5002                 sig->generic_param_count = old->generic_param_count;
5003                 sig->param_count = old->param_count + nargs;
5004                 sig->sentinelpos = old->param_count;
5005                 sig->ret = old->ret;
5006
5007                 for (i = 0; i < old->param_count; i++)
5008                         sig->params [i] = old->params [i];
5009
5010                 for (i = 0; i < nargs; i++) {
5011                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5012                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5013                 }
5014
5015                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5016                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5017                 parent >>= MONO_TYPEDEFORREF_BITS;
5018
5019                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5020                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5021
5022                 sig_token = method_encode_signature (assembly, sig);
5023                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5024         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5025                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5026                 ReflectionMethodBuilder rmb;
5027                 guint32 parent, sig_token;
5028                 int nopt_args, nparams, ngparams, i;
5029                 char *name;
5030
5031                 reflection_methodbuilder_from_method_builder (&rmb, mb);
5032                 rmb.opt_types = opt_param_types;
5033                 nopt_args = mono_array_length (opt_param_types);
5034
5035                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5036                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5037                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5038
5039                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5040                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5041                 sig->call_convention = rmb.call_conv;
5042                 sig->generic_param_count = ngparams;
5043                 sig->param_count = nparams + nopt_args;
5044                 sig->sentinelpos = nparams;
5045                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5046
5047                 for (i = 0; i < nparams; i++) {
5048                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5049                         sig->params [i] = mono_reflection_type_get_handle (rt);
5050                 }
5051
5052                 for (i = 0; i < nopt_args; i++) {
5053                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5054                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5055                 }
5056
5057                 sig_token = method_builder_encode_signature (assembly, &rmb);
5058
5059                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
5060                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5061
5062                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5063                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5064
5065                 name = mono_string_to_utf8 (rmb.name);
5066                 token = mono_image_get_varargs_method_token (
5067                         assembly, parent, name, sig_token);
5068                 g_free (name);
5069         } else {
5070                 g_error ("requested method token for %s\n", klass->name);
5071         }
5072
5073         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5074         register_dyn_token (assembly, token, obj);
5075         return token;
5076 }
5077
5078 /*
5079  * mono_image_create_token:
5080  * @assembly: a dynamic assembly
5081  * @obj:
5082  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5083  *
5084  * Get a token to insert in the IL code stream for the given MemberInfo.
5085  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5086  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5087  * entry.
5088  */
5089 guint32
5090 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5091                                                  gboolean create_open_instance, gboolean register_token)
5092 {
5093         MonoClass *klass;
5094         guint32 token = 0;
5095
5096         klass = obj->vtable->klass;
5097
5098         /* Check for user defined reflection objects */
5099         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5100         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
5101                 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
5102
5103         if (strcmp (klass->name, "MethodBuilder") == 0) {
5104                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5105                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5106
5107                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5108                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5109                 else
5110                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
5111                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5112         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5113                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5114                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5115
5116                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5117                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5118                 else
5119                         token = mono_image_get_ctorbuilder_token (assembly, mb);
5120                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5121         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5122                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5123                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5124                 if (tb->generic_params) {
5125                         token = mono_image_get_generic_field_token (assembly, fb);
5126                 } else {
5127                         if (tb->module->dynamic_image == assembly) {
5128                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5129                         } else {
5130                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5131                         }
5132                 }
5133         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5134                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5135                 if (create_open_instance && tb->generic_params) {
5136                         MonoType *type;
5137                         init_type_builder_generics (obj);
5138                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5139                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5140                         token = mono_metadata_token_from_dor (token);
5141                 } else if (tb->module->dynamic_image == assembly) {
5142                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5143                 } else {
5144                         MonoType *type;
5145                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5146                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5147                 }
5148         } else if (strcmp (klass->name, "MonoType") == 0) {
5149                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5150                 MonoClass *mc = mono_class_from_mono_type (type);
5151                 token = mono_metadata_token_from_dor (
5152                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5153         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5154                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5155                 token = mono_metadata_token_from_dor (
5156                         mono_image_typedef_or_ref (assembly, type));
5157         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5158                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5159                 token = mono_metadata_token_from_dor (
5160                         mono_image_typedef_or_ref (assembly, type));
5161         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5162                    strcmp (klass->name, "MonoMethod") == 0 ||
5163                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5164                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5165                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5166                 if (m->method->is_inflated) {
5167                         if (create_open_instance)
5168                                 token = mono_image_get_methodspec_token (assembly, m->method);
5169                         else
5170                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5171                 } else if ((m->method->klass->image == &assembly->image) &&
5172                          !m->method->klass->generic_class) {
5173                         static guint32 method_table_idx = 0xffffff;
5174                         if (m->method->klass->wastypebuilder) {
5175                                 /* we use the same token as the one that was assigned
5176                                  * to the Methodbuilder.
5177                                  * FIXME: do the equivalent for Fields.
5178                                  */
5179                                 token = m->method->token;
5180                         } else {
5181                                 /*
5182                                  * Each token should have a unique index, but the indexes are
5183                                  * assigned by managed code, so we don't know about them. An
5184                                  * easy solution is to count backwards...
5185                                  */
5186                                 method_table_idx --;
5187                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5188                         }
5189                 } else {
5190                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5191                 }
5192                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5193         } else if (strcmp (klass->name, "MonoField") == 0) {
5194                 MonoReflectionField *f = (MonoReflectionField *)obj;
5195                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5196                         static guint32 field_table_idx = 0xffffff;
5197                         field_table_idx --;
5198                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5199                 } else {
5200                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5201                 }
5202                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5203         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5204                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5205                 token = mono_image_get_array_token (assembly, m);
5206         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5207                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5208                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5209         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5210                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5211                 token = mono_metadata_token_from_dor (
5212                         mono_image_typedef_or_ref (assembly, type));
5213         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5214                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5215                 token = mono_image_get_field_on_inst_token (assembly, f);
5216         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5217                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5218                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5219         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5220                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5221                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5222         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5223                 MonoReflectionType *type = (MonoReflectionType *)obj;
5224                 token = mono_metadata_token_from_dor (
5225                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5226         } else {
5227                 g_error ("requested token for %s\n", klass->name);
5228         }
5229
5230         if (register_token)
5231                 mono_image_register_token (assembly, token, obj);
5232
5233         return token;
5234 }
5235
5236 /*
5237  * mono_image_register_token:
5238  *
5239  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5240  * the Module.ResolveXXXToken () methods to work.
5241  */
5242 void
5243 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5244 {
5245         MonoObject *prev;
5246
5247         dynamic_image_lock (assembly);
5248         prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5249         if (prev) {
5250                 /* There could be multiple MethodInfo objects with the same token */
5251                 //g_assert (prev == obj);
5252         } else {
5253                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5254         }
5255         dynamic_image_unlock (assembly);
5256 }
5257
5258 static MonoDynamicImage*
5259 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5260 {
5261         static const guchar entrycode [16] = {0xff, 0x25, 0};
5262         MonoDynamicImage *image;
5263         int i;
5264
5265         const char *version;
5266
5267         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5268                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5269         else
5270                 version = mono_get_runtime_info ()->runtime_version;
5271
5272 #if HAVE_BOEHM_GC
5273         /* The MonoGHashTable's need GC tracking */
5274         image = GC_MALLOC (sizeof (MonoDynamicImage));
5275 #else
5276         image = g_new0 (MonoDynamicImage, 1);
5277 #endif
5278
5279         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5280         
5281         /*g_print ("created image %p\n", image);*/
5282         /* keep in sync with image.c */
5283         image->image.name = assembly_name;
5284         image->image.assembly_name = image->image.name; /* they may be different */
5285         image->image.module_name = module_name;
5286         image->image.version = g_strdup (version);
5287         image->image.md_version_major = 1;
5288         image->image.md_version_minor = 1;
5289         image->image.dynamic = TRUE;
5290
5291         image->image.references = g_new0 (MonoAssembly*, 1);
5292         image->image.references [0] = NULL;
5293
5294         mono_image_init (&image->image);
5295
5296         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");
5297         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5298         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5299         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5300         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5301         image->handleref = g_hash_table_new (NULL, NULL);
5302         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");
5303         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5304         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");
5305         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");
5306         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5307         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5308         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5309         image->gen_params = g_ptr_array_new ();
5310         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5311
5312         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5313         string_heap_init (&image->sheap);
5314         mono_image_add_stream_data (&image->us, "", 1);
5315         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5316         /* import tables... */
5317         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5318         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5319         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5320         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5321         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5322         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5323         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5324         stream_data_align (&image->code);
5325
5326         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5327
5328         for (i=0; i < MONO_TABLE_NUM; ++i) {
5329                 image->tables [i].next_idx = 1;
5330                 image->tables [i].columns = table_sizes [i];
5331         }
5332
5333         image->image.assembly = (MonoAssembly*)assembly;
5334         image->run = assembly->run;
5335         image->save = assembly->save;
5336         image->pe_kind = 0x1; /* ILOnly */
5337         image->machine = 0x14c; /* I386 */
5338         
5339         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5340
5341         return image;
5342 }
5343 #endif
5344
5345 static void
5346 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5347 {
5348         g_free (key);
5349 }
5350
5351 static void
5352 release_hashtable (MonoGHashTable **hash)
5353 {
5354         if (*hash) {
5355                 mono_g_hash_table_destroy (*hash);
5356                 *hash = NULL;
5357         }
5358 }
5359
5360 void
5361 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5362 {
5363         release_hashtable (&image->token_fixups);
5364         release_hashtable (&image->handleref_managed);
5365         release_hashtable (&image->tokens);
5366         release_hashtable (&image->remapped_tokens);
5367         release_hashtable (&image->generic_def_objects);
5368         release_hashtable (&image->methodspec);
5369 }
5370
5371 void
5372 mono_dynamic_image_free (MonoDynamicImage *image)
5373 {
5374         MonoDynamicImage *di = image;
5375         GList *list;
5376         int i;
5377
5378         if (di->methodspec)
5379                 mono_g_hash_table_destroy (di->methodspec);
5380         if (di->typespec)
5381                 g_hash_table_destroy (di->typespec);
5382         if (di->typeref)
5383                 g_hash_table_destroy (di->typeref);
5384         if (di->handleref)
5385                 g_hash_table_destroy (di->handleref);
5386         if (di->handleref_managed)
5387                 mono_g_hash_table_destroy (di->handleref_managed);
5388         if (di->tokens)
5389                 mono_g_hash_table_destroy (di->tokens);
5390         if (di->remapped_tokens)
5391                 mono_g_hash_table_destroy (di->remapped_tokens);
5392         if (di->generic_def_objects)
5393                 mono_g_hash_table_destroy (di->generic_def_objects);
5394         if (di->blob_cache) {
5395                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5396                 g_hash_table_destroy (di->blob_cache);
5397         }
5398         if (di->standalonesig_cache)
5399                 g_hash_table_destroy (di->standalonesig_cache);
5400         for (list = di->array_methods; list; list = list->next) {
5401                 ArrayMethod *am = (ArrayMethod *)list->data;
5402                 g_free (am->sig);
5403                 g_free (am->name);
5404                 g_free (am);
5405         }
5406         g_list_free (di->array_methods);
5407         if (di->gen_params) {
5408                 for (i = 0; i < di->gen_params->len; i++) {
5409                         GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5410                         mono_gc_deregister_root ((char*) &entry->gparam);
5411                         g_free (entry);
5412                 }
5413                 g_ptr_array_free (di->gen_params, TRUE);
5414         }
5415         if (di->token_fixups)
5416                 mono_g_hash_table_destroy (di->token_fixups);
5417         if (di->method_to_table_idx)
5418                 g_hash_table_destroy (di->method_to_table_idx);
5419         if (di->field_to_table_idx)
5420                 g_hash_table_destroy (di->field_to_table_idx);
5421         if (di->method_aux_hash)
5422                 g_hash_table_destroy (di->method_aux_hash);
5423         if (di->vararg_aux_hash)
5424                 g_hash_table_destroy (di->vararg_aux_hash);
5425         g_free (di->strong_name);
5426         g_free (di->win32_res);
5427         if (di->public_key)
5428                 g_free (di->public_key);
5429
5430         /*g_print ("string heap destroy for image %p\n", di);*/
5431         mono_dynamic_stream_reset (&di->sheap);
5432         mono_dynamic_stream_reset (&di->code);
5433         mono_dynamic_stream_reset (&di->resources);
5434         mono_dynamic_stream_reset (&di->us);
5435         mono_dynamic_stream_reset (&di->blob);
5436         mono_dynamic_stream_reset (&di->tstream);
5437         mono_dynamic_stream_reset (&di->guid);
5438         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5439                 g_free (di->tables [i].values);
5440         }
5441 }       
5442
5443 void
5444 mono_dynamic_image_free_image (MonoDynamicImage *image)
5445 {
5446         /* See create_dynamic_mono_image () */
5447 #if HAVE_BOEHM_GC
5448         /* Allocated using GC_MALLOC */
5449 #else
5450         g_free (image);
5451 #endif
5452 }
5453
5454 #ifndef DISABLE_REFLECTION_EMIT
5455
5456 /*
5457  * mono_image_basic_init:
5458  * @assembly: an assembly builder object
5459  *
5460  * Create the MonoImage that represents the assembly builder and setup some
5461  * of the helper hash table and the basic metadata streams.
5462  */
5463 void
5464 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5465 {
5466         MonoDynamicAssembly *assembly;
5467         MonoDynamicImage *image;
5468         MonoDomain *domain = mono_object_domain (assemblyb);
5469         
5470         if (assemblyb->dynamic_assembly)
5471                 return;
5472
5473 #if HAVE_BOEHM_GC
5474         /* assembly->assembly.image might be GC allocated */
5475         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5476 #else
5477         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5478 #endif
5479
5480         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5481         
5482         assembly->assembly.ref_count = 1;
5483         assembly->assembly.dynamic = TRUE;
5484         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5485         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5486         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5487         if (assemblyb->culture)
5488                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5489         else
5490                 assembly->assembly.aname.culture = g_strdup ("");
5491
5492         if (assemblyb->version) {
5493                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5494                         char **version = g_strsplit (vstr, ".", 4);
5495                         char **parts = version;
5496                         assembly->assembly.aname.major = atoi (*parts++);
5497                         assembly->assembly.aname.minor = atoi (*parts++);
5498                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5499                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5500
5501                         g_strfreev (version);
5502                         g_free (vstr);
5503         } else {
5504                         assembly->assembly.aname.major = 0;
5505                         assembly->assembly.aname.minor = 0;
5506                         assembly->assembly.aname.build = 0;
5507                         assembly->assembly.aname.revision = 0;
5508         }
5509
5510         assembly->run = assemblyb->access != 2;
5511         assembly->save = assemblyb->access != 1;
5512         assembly->domain = domain;
5513
5514         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5515         image->initial_image = TRUE;
5516         assembly->assembly.aname.name = image->image.name;
5517         assembly->assembly.image = &image->image;
5518         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5519                 /* -1 to correct for the trailing NULL byte */
5520                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5521                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5522                 }
5523                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5524         }
5525
5526         mono_domain_assemblies_lock (domain);
5527         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5528         mono_domain_assemblies_unlock (domain);
5529
5530         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5531         
5532         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5533         
5534         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5535 }
5536
5537 #endif /* !DISABLE_REFLECTION_EMIT */
5538
5539 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5540
5541 static int
5542 calc_section_size (MonoDynamicImage *assembly)
5543 {
5544         int nsections = 0;
5545
5546         /* alignment constraints */
5547         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5548         g_assert ((assembly->code.index % 4) == 0);
5549         assembly->meta_size += 3;
5550         assembly->meta_size &= ~3;
5551         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5552         g_assert ((assembly->resources.index % 4) == 0);
5553
5554         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5555         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5556         nsections++;
5557
5558         if (assembly->win32_res) {
5559                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5560
5561                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5562                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5563                 nsections++;
5564         }
5565
5566         assembly->sections [MONO_SECTION_RELOC].size = 12;
5567         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5568         nsections++;
5569
5570         return nsections;
5571 }
5572
5573 typedef struct {
5574         guint32 id;
5575         guint32 offset;
5576         GSList *children;
5577         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5578 } ResTreeNode;
5579
5580 static int
5581 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5582 {
5583         ResTreeNode *t1 = (ResTreeNode*)a;
5584         ResTreeNode *t2 = (ResTreeNode*)b;
5585
5586         return t1->id - t2->id;
5587 }
5588
5589 /*
5590  * resource_tree_create:
5591  *
5592  *  Organize the resources into a resource tree.
5593  */
5594 static ResTreeNode *
5595 resource_tree_create (MonoArray *win32_resources)
5596 {
5597         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5598         GSList *l;
5599         int i;
5600
5601         tree = g_new0 (ResTreeNode, 1);
5602         
5603         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5604                 MonoReflectionWin32Resource *win32_res =
5605                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5606
5607                 /* Create node */
5608
5609                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5610                 lang_node = g_new0 (ResTreeNode, 1);
5611                 lang_node->id = win32_res->lang_id;
5612                 lang_node->win32_res = win32_res;
5613
5614                 /* Create type node if neccesary */
5615                 type_node = NULL;
5616                 for (l = tree->children; l; l = l->next)
5617                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5618                                 type_node = (ResTreeNode*)l->data;
5619                                 break;
5620                         }
5621
5622                 if (!type_node) {
5623                         type_node = g_new0 (ResTreeNode, 1);
5624                         type_node->id = win32_res->res_type;
5625
5626                         /* 
5627                          * The resource types have to be sorted otherwise
5628                          * Windows Explorer can't display the version information.
5629                          */
5630                         tree->children = g_slist_insert_sorted (tree->children, 
5631                                 type_node, resource_tree_compare_by_id);
5632                 }
5633
5634                 /* Create res node if neccesary */
5635                 res_node = NULL;
5636                 for (l = type_node->children; l; l = l->next)
5637                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5638                                 res_node = (ResTreeNode*)l->data;
5639                                 break;
5640                         }
5641
5642                 if (!res_node) {
5643                         res_node = g_new0 (ResTreeNode, 1);
5644                         res_node->id = win32_res->res_id;
5645                         type_node->children = g_slist_append (type_node->children, res_node);
5646                 }
5647
5648                 res_node->children = g_slist_append (res_node->children, lang_node);
5649         }
5650
5651         return tree;
5652 }
5653
5654 /*
5655  * resource_tree_encode:
5656  * 
5657  *   Encode the resource tree into the format used in the PE file.
5658  */
5659 static void
5660 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5661 {
5662         char *entries;
5663         MonoPEResourceDir dir;
5664         MonoPEResourceDirEntry dir_entry;
5665         MonoPEResourceDataEntry data_entry;
5666         GSList *l;
5667         guint32 res_id_entries;
5668
5669         /*
5670          * For the format of the resource directory, see the article
5671          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5672          * Matt Pietrek
5673          */
5674
5675         memset (&dir, 0, sizeof (dir));
5676         memset (&dir_entry, 0, sizeof (dir_entry));
5677         memset (&data_entry, 0, sizeof (data_entry));
5678
5679         g_assert (sizeof (dir) == 16);
5680         g_assert (sizeof (dir_entry) == 8);
5681         g_assert (sizeof (data_entry) == 16);
5682
5683         node->offset = p - begin;
5684
5685         /* IMAGE_RESOURCE_DIRECTORY */
5686         res_id_entries = g_slist_length (node->children);
5687         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5688
5689         memcpy (p, &dir, sizeof (dir));
5690         p += sizeof (dir);
5691
5692         /* Reserve space for entries */
5693         entries = p;
5694         p += sizeof (dir_entry) * res_id_entries;
5695
5696         /* Write children */
5697         for (l = node->children; l; l = l->next) {
5698                 ResTreeNode *child = (ResTreeNode*)l->data;
5699
5700                 if (child->win32_res) {
5701                         guint32 size;
5702
5703                         child->offset = p - begin;
5704
5705                         /* IMAGE_RESOURCE_DATA_ENTRY */
5706                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5707                         size = mono_array_length (child->win32_res->res_data);
5708                         data_entry.rde_size = GUINT32_TO_LE (size);
5709
5710                         memcpy (p, &data_entry, sizeof (data_entry));
5711                         p += sizeof (data_entry);
5712
5713                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5714                         p += size;
5715                 } else {
5716                         resource_tree_encode (child, begin, p, &p);
5717                 }
5718         }
5719
5720         /* IMAGE_RESOURCE_ENTRY */
5721         for (l = node->children; l; l = l->next) {
5722                 ResTreeNode *child = (ResTreeNode*)l->data;
5723
5724                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5725                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5726
5727                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5728                 entries += sizeof (dir_entry);
5729         }
5730
5731         *endbuf = p;
5732 }
5733
5734 static void
5735 resource_tree_free (ResTreeNode * node)
5736 {
5737         GSList * list;
5738         for (list = node->children; list; list = list->next)
5739                 resource_tree_free ((ResTreeNode*)list->data);
5740         g_slist_free(node->children);
5741         g_free (node);
5742 }
5743
5744 static void
5745 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5746 {
5747         char *buf;
5748         char *p;
5749         guint32 size, i;
5750         MonoReflectionWin32Resource *win32_res;
5751         ResTreeNode *tree;
5752
5753         if (!assemblyb->win32_resources)
5754                 return;
5755
5756         /*
5757          * Resources are stored in a three level tree inside the PE file.
5758          * - level one contains a node for each type of resource
5759          * - level two contains a node for each resource
5760          * - level three contains a node for each instance of a resource for a
5761          *   specific language.
5762          */
5763
5764         tree = resource_tree_create (assemblyb->win32_resources);
5765
5766         /* Estimate the size of the encoded tree */
5767         size = 0;
5768         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5769                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5770                 size += mono_array_length (win32_res->res_data);
5771         }
5772         /* Directory structure */
5773         size += mono_array_length (assemblyb->win32_resources) * 256;
5774         p = buf = g_malloc (size);
5775
5776         resource_tree_encode (tree, p, p, &p);
5777
5778         g_assert (p - buf <= size);
5779
5780         assembly->win32_res = g_malloc (p - buf);
5781         assembly->win32_res_size = p - buf;
5782         memcpy (assembly->win32_res, buf, p - buf);
5783
5784         g_free (buf);
5785         resource_tree_free (tree);
5786 }
5787
5788 static void
5789 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5790 {
5791         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5792         int i;
5793
5794         p += sizeof (MonoPEResourceDir);
5795         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5796                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5797                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5798                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5799                         fixup_resource_directory (res_section, child, rva);
5800                 } else {
5801                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5802                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5803                 }
5804
5805                 p += sizeof (MonoPEResourceDirEntry);
5806         }
5807 }
5808
5809 static void
5810 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5811 {
5812         guint32 dummy;
5813         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5814                 g_error ("WriteFile returned %d\n", GetLastError ());
5815 }
5816
5817 /*
5818  * mono_image_create_pefile:
5819  * @mb: a module builder object
5820  * 
5821  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
5822  * assembly->pefile where it can be easily retrieved later in chunks.
5823  */
5824 void
5825 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5826 {
5827         MonoMSDOSHeader *msdos;
5828         MonoDotNetHeader *header;
5829         MonoSectionTable *section;
5830         MonoCLIHeader *cli_header;
5831         guint32 size, image_size, virtual_base, text_offset;
5832         guint32 header_start, section_start, file_offset, virtual_offset;
5833         MonoDynamicImage *assembly;
5834         MonoReflectionAssemblyBuilder *assemblyb;
5835         MonoDynamicStream pefile_stream = {0};
5836         MonoDynamicStream *pefile = &pefile_stream;
5837         int i, nsections;
5838         guint32 *rva, value;
5839         guchar *p;
5840         static const unsigned char msheader[] = {
5841                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5842                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5843                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5844                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5845                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5846                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5847                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5848                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5849         };
5850
5851         assemblyb = mb->assemblyb;
5852
5853         mono_image_basic_init (assemblyb);
5854         assembly = mb->dynamic_image;
5855
5856         assembly->pe_kind = assemblyb->pe_kind;
5857         assembly->machine = assemblyb->machine;
5858         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5859         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5860         
5861         mono_image_build_metadata (mb);
5862
5863         if (mb->is_main && assemblyb->resources) {
5864                 int len = mono_array_length (assemblyb->resources);
5865                 for (i = 0; i < len; ++i)
5866                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5867         }
5868
5869         if (mb->resources) {
5870                 int len = mono_array_length (mb->resources);
5871                 for (i = 0; i < len; ++i)
5872                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5873         }
5874
5875         build_compressed_metadata (assembly);
5876
5877         if (mb->is_main)
5878                 assembly_add_win32_resources (assembly, assemblyb);
5879
5880         nsections = calc_section_size (assembly);
5881         
5882         /* The DOS header and stub */
5883         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5884         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5885
5886         /* the dotnet header */
5887         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5888
5889         /* the section tables */
5890         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5891
5892         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5893         virtual_offset = VIRT_ALIGN;
5894         image_size = 0;
5895
5896         for (i = 0; i < MONO_SECTION_MAX; ++i) {
5897                 if (!assembly->sections [i].size)
5898                         continue;
5899                 /* align offsets */
5900                 file_offset += FILE_ALIGN - 1;
5901                 file_offset &= ~(FILE_ALIGN - 1);
5902                 virtual_offset += VIRT_ALIGN - 1;
5903                 virtual_offset &= ~(VIRT_ALIGN - 1);
5904
5905                 assembly->sections [i].offset = file_offset;
5906                 assembly->sections [i].rva = virtual_offset;
5907
5908                 file_offset += assembly->sections [i].size;
5909                 virtual_offset += assembly->sections [i].size;
5910                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5911         }
5912
5913         file_offset += FILE_ALIGN - 1;
5914         file_offset &= ~(FILE_ALIGN - 1);
5915
5916         image_size += section_start + sizeof (MonoSectionTable) * nsections;
5917
5918         /* back-patch info */
5919         msdos = (MonoMSDOSHeader*)pefile->data;
5920         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5921
5922         header = (MonoDotNetHeader*)(pefile->data + header_start);
5923         header->pesig [0] = 'P';
5924         header->pesig [1] = 'E';
5925         
5926         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5927         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5928         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5929         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5930         if (assemblyb->pekind == 1) {
5931                 /* it's a dll */
5932                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5933         } else {
5934                 /* it's an exe */
5935                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5936         }
5937
5938         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5939
5940         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5941         header->pe.pe_major = 6;
5942         header->pe.pe_minor = 0;
5943         size = assembly->sections [MONO_SECTION_TEXT].size;
5944         size += FILE_ALIGN - 1;
5945         size &= ~(FILE_ALIGN - 1);
5946         header->pe.pe_code_size = GUINT32_FROM_LE(size);
5947         size = assembly->sections [MONO_SECTION_RSRC].size;
5948         size += FILE_ALIGN - 1;
5949         size &= ~(FILE_ALIGN - 1);
5950         header->pe.pe_data_size = GUINT32_FROM_LE(size);
5951         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5952         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5953         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5954         /* pe_rva_entry_point always at the beginning of the text section */
5955         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5956
5957         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5958         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5959         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5960         header->nt.pe_os_major = GUINT16_FROM_LE (4);
5961         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5962         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5963         size = section_start;
5964         size += FILE_ALIGN - 1;
5965         size &= ~(FILE_ALIGN - 1);
5966         header->nt.pe_header_size = GUINT32_FROM_LE (size);
5967         size = image_size;
5968         size += VIRT_ALIGN - 1;
5969         size &= ~(VIRT_ALIGN - 1);
5970         header->nt.pe_image_size = GUINT32_FROM_LE (size);
5971
5972         /*
5973         // Translate the PEFileKind value to the value expected by the Windows loader
5974         */
5975         {
5976                 short kind;
5977
5978                 /*
5979                 // PEFileKinds.Dll == 1
5980                 // PEFileKinds.ConsoleApplication == 2
5981                 // PEFileKinds.WindowApplication == 3
5982                 //
5983                 // need to get:
5984                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5985                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5986                 */
5987                 if (assemblyb->pekind == 3)
5988                         kind = 2;
5989                 else
5990                         kind = 3;
5991                 
5992                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5993         }    
5994         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5995         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5996         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5997         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5998         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5999         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6000
6001         /* fill data directory entries */
6002
6003         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6004         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6005
6006         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6007         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6008
6009         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6010         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6011         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6012         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6013         /* patch entrypoint name */
6014         if (assemblyb->pekind == 1)
6015                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6016         else
6017                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6018         /* patch imported function RVA name */
6019         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6020         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6021
6022         /* the import table */
6023         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6024         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6025         /* patch imported dll RVA name and other entries in the dir */
6026         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6027         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6028         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6029         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6030         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6031         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6032
6033         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6034         value = (assembly->text_rva + assembly->imp_names_offset);
6035         *p++ = (value) & 0xff;
6036         *p++ = (value >> 8) & (0xff);
6037         *p++ = (value >> 16) & (0xff);
6038         *p++ = (value >> 24) & (0xff);
6039
6040         /* the CLI header info */
6041         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6042         cli_header->ch_size = GUINT32_FROM_LE (72);
6043         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6044         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6045         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6046         if (assemblyb->entry_point) {
6047                 guint32 table_idx = 0;
6048                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6049                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6050                         table_idx = methodb->table_idx;
6051                 } else {
6052                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6053                 }
6054                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6055         } else {
6056                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6057         }
6058         /* The embedded managed resources */
6059         text_offset = assembly->text_rva + assembly->code.index;
6060         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6061         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6062         text_offset += assembly->resources.index;
6063         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6064         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6065         text_offset += assembly->meta_size;
6066         if (assembly->strong_name_size) {
6067                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6068                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6069                 text_offset += assembly->strong_name_size;
6070         }
6071
6072         /* write the section tables and section content */
6073         section = (MonoSectionTable*)(pefile->data + section_start);
6074         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6075                 static const char section_names [][7] = {
6076                         ".text", ".rsrc", ".reloc"
6077                 };
6078                 if (!assembly->sections [i].size)
6079                         continue;
6080                 strcpy (section->st_name, section_names [i]);
6081                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6082                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6083                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6084                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6085                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6086                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6087                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6088                 section ++;
6089         }
6090         
6091         checked_write_file (file, pefile->data, pefile->index);
6092         
6093         mono_dynamic_stream_reset (pefile);
6094         
6095         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6096                 if (!assembly->sections [i].size)
6097                         continue;
6098                 
6099                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6100                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6101                 
6102                 switch (i) {
6103                 case MONO_SECTION_TEXT:
6104                         /* patch entry point */
6105                         p = (guchar*)(assembly->code.data + 2);
6106                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6107                         *p++ = (value) & 0xff;
6108                         *p++ = (value >> 8) & 0xff;
6109                         *p++ = (value >> 16) & 0xff;
6110                         *p++ = (value >> 24) & 0xff;
6111                 
6112                         checked_write_file (file, assembly->code.data, assembly->code.index);
6113                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6114                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6115                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6116                                 
6117
6118                         g_free (assembly->image.raw_metadata);
6119                         break;
6120                 case MONO_SECTION_RELOC: {
6121                         struct {
6122                                 guint32 page_rva;
6123                                 guint32 block_size;
6124                                 guint16 type_and_offset;
6125                                 guint16 term;
6126                         } reloc;
6127                         
6128                         g_assert (sizeof (reloc) == 12);
6129                         
6130                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6131                         reloc.block_size = GUINT32_FROM_LE (12);
6132                         
6133                         /* 
6134                          * the entrypoint is always at the start of the text section 
6135                          * 3 is IMAGE_REL_BASED_HIGHLOW
6136                          * 2 is patch_size_rva - text_rva
6137                          */
6138                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6139                         reloc.term = 0;
6140                         
6141                         checked_write_file (file, &reloc, sizeof (reloc));
6142                         
6143                         break;
6144                 }
6145                 case MONO_SECTION_RSRC:
6146                         if (assembly->win32_res) {
6147
6148                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6149                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6150                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6151                         }
6152                         break;
6153                 default:
6154                         g_assert_not_reached ();
6155                 }
6156         }
6157         
6158         /* check that the file is properly padded */
6159         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6160                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6161         if (! SetEndOfFile (file))
6162                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6163         
6164         mono_dynamic_stream_reset (&assembly->code);
6165         mono_dynamic_stream_reset (&assembly->us);
6166         mono_dynamic_stream_reset (&assembly->blob);
6167         mono_dynamic_stream_reset (&assembly->guid);
6168         mono_dynamic_stream_reset (&assembly->sheap);
6169
6170         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6171         g_hash_table_destroy (assembly->blob_cache);
6172         assembly->blob_cache = NULL;
6173 }
6174
6175 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6176
6177 void
6178 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
6179 {
6180         g_assert_not_reached ();
6181 }
6182
6183 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6184
6185 #ifndef DISABLE_REFLECTION_EMIT
6186
6187 MonoReflectionModule *
6188 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6189 {
6190         char *name;
6191         MonoImage *image;
6192         MonoImageOpenStatus status;
6193         MonoDynamicAssembly *assembly;
6194         guint32 module_count;
6195         MonoImage **new_modules;
6196         gboolean *new_modules_loaded;
6197         
6198         name = mono_string_to_utf8 (fileName);
6199
6200         image = mono_image_open (name, &status);
6201         if (!image) {
6202                 MonoException *exc;
6203                 if (status == MONO_IMAGE_ERROR_ERRNO)
6204                         exc = mono_get_exception_file_not_found (fileName);
6205                 else
6206                         exc = mono_get_exception_bad_image_format (name);
6207                 g_free (name);
6208                 mono_raise_exception (exc);
6209         }
6210
6211         g_free (name);
6212
6213         assembly = ab->dynamic_assembly;
6214         image->assembly = (MonoAssembly*)assembly;
6215
6216         module_count = image->assembly->image->module_count;
6217         new_modules = g_new0 (MonoImage *, module_count + 1);
6218         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6219
6220         if (image->assembly->image->modules)
6221                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6222         if (image->assembly->image->modules_loaded)
6223                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6224         new_modules [module_count] = image;
6225         new_modules_loaded [module_count] = TRUE;
6226         mono_image_addref (image);
6227
6228         g_free (image->assembly->image->modules);
6229         image->assembly->image->modules = new_modules;
6230         image->assembly->image->modules_loaded = new_modules_loaded;
6231         image->assembly->image->module_count ++;
6232
6233         mono_assembly_load_references (image, &status);
6234         if (status) {
6235                 mono_image_close (image);
6236                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6237         }
6238
6239         return mono_module_get_object (mono_domain_get (), image);
6240 }
6241
6242 #endif /* DISABLE_REFLECTION_EMIT */
6243
6244 /*
6245  * We need to return always the same object for MethodInfo, FieldInfo etc..
6246  * but we need to consider the reflected type.
6247  * type uses a different hash, since it uses custom hash/equal functions.
6248  */
6249
6250 typedef struct {
6251         gpointer item;
6252         MonoClass *refclass;
6253 } ReflectedEntry;
6254
6255 static gboolean
6256 reflected_equal (gconstpointer a, gconstpointer b) {
6257         const ReflectedEntry *ea = a;
6258         const ReflectedEntry *eb = b;
6259
6260         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6261 }
6262
6263 static guint
6264 reflected_hash (gconstpointer a) {
6265         const ReflectedEntry *ea = a;
6266         return mono_aligned_addr_hash (ea->item);
6267 }
6268
6269 #define CHECK_OBJECT(t,p,k)     \
6270         do {    \
6271                 t _obj; \
6272                 ReflectedEntry e;       \
6273                 e.item = (p);   \
6274                 e.refclass = (k);       \
6275                 mono_domain_lock (domain);      \
6276                 if (!domain->refobject_hash)    \
6277                         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");  \
6278                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
6279                         mono_domain_unlock (domain);    \
6280                         return _obj;    \
6281                 }       \
6282         mono_domain_unlock (domain); \
6283         } while (0)
6284
6285 #ifdef HAVE_BOEHM_GC
6286 /* ReflectedEntry doesn't need to be GC tracked */
6287 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6288 #define FREE_REFENTRY(entry) g_free ((entry))
6289 #define REFENTRY_REQUIRES_CLEANUP
6290 #else
6291 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6292 /* FIXME: */
6293 #define FREE_REFENTRY(entry)
6294 #endif
6295
6296 #define CACHE_OBJECT(t,p,o,k)   \
6297         do {    \
6298                 t _obj; \
6299         ReflectedEntry pe; \
6300         pe.item = (p); \
6301         pe.refclass = (k); \
6302         mono_domain_lock (domain); \
6303                 if (!domain->refobject_hash)    \
6304                         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");  \
6305         _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6306         if (!_obj) { \
6307                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6308                     e->item = (p);      \
6309                     e->refclass = (k);  \
6310                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6311             _obj = o; \
6312         } \
6313                 mono_domain_unlock (domain);    \
6314         return _obj; \
6315         } while (0)
6316
6317 static void
6318 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6319 {
6320         mono_domain_lock (domain);
6321         if (domain->refobject_hash) {
6322         ReflectedEntry pe;
6323                 gpointer orig_pe, orig_value;
6324
6325                 pe.item = o;
6326                 pe.refclass = klass;
6327                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6328                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6329                         FREE_REFENTRY (orig_pe);
6330                 }
6331         }
6332         mono_domain_unlock (domain);
6333 }
6334
6335 #ifdef REFENTRY_REQUIRES_CLEANUP
6336 static void
6337 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6338 {
6339         FREE_REFENTRY (key);
6340 }
6341 #endif
6342
6343 void
6344 mono_reflection_cleanup_domain (MonoDomain *domain)
6345 {
6346         if (domain->refobject_hash) {
6347 /*let's avoid scanning the whole hashtable if not needed*/
6348 #ifdef REFENTRY_REQUIRES_CLEANUP
6349                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6350 #endif
6351                 mono_g_hash_table_destroy (domain->refobject_hash);
6352                 domain->refobject_hash = NULL;
6353         }
6354 }
6355
6356 #ifndef DISABLE_REFLECTION_EMIT
6357 static gpointer
6358 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6359 {
6360         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6361 }
6362
6363 static gpointer
6364 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6365 {
6366         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6367 }
6368
6369 void
6370 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6371 {
6372         MonoDynamicImage *image = moduleb->dynamic_image;
6373         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6374         if (!image) {
6375                 MonoError error;
6376                 int module_count;
6377                 MonoImage **new_modules;
6378                 MonoImage *ass;
6379                 char *name, *fqname;
6380                 /*
6381                  * FIXME: we already created an image in mono_image_basic_init (), but
6382                  * we don't know which module it belongs to, since that is only 
6383                  * determined at assembly save time.
6384                  */
6385                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6386                 name = mono_string_to_utf8 (ab->name);
6387                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6388                 if (!mono_error_ok (&error)) {
6389                         g_free (name);
6390                         mono_error_raise_exception (&error);
6391                 }
6392                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6393
6394                 moduleb->module.image = &image->image;
6395                 moduleb->dynamic_image = image;
6396                 register_module (mono_object_domain (moduleb), moduleb, image);
6397
6398                 /* register the module with the assembly */
6399                 ass = ab->dynamic_assembly->assembly.image;
6400                 module_count = ass->module_count;
6401                 new_modules = g_new0 (MonoImage *, module_count + 1);
6402
6403                 if (ass->modules)
6404                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6405                 new_modules [module_count] = &image->image;
6406                 mono_image_addref (&image->image);
6407
6408                 g_free (ass->modules);
6409                 ass->modules = new_modules;
6410                 ass->module_count ++;
6411         }
6412 }
6413
6414 void
6415 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6416 {
6417         MonoDynamicImage *image = moduleb->dynamic_image;
6418
6419         g_assert (type->type);
6420         image->wrappers_type = mono_class_from_mono_type (type->type);
6421 }
6422
6423 #endif
6424
6425 /*
6426  * mono_assembly_get_object:
6427  * @domain: an app domain
6428  * @assembly: an assembly
6429  *
6430  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6431  */
6432 MonoReflectionAssembly*
6433 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6434 {
6435         static MonoClass *assembly_type;
6436         MonoReflectionAssembly *res;
6437         
6438         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6439         if (!assembly_type) {
6440                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6441                 if (class == NULL)
6442                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6443                 g_assert (class);
6444                 assembly_type = class;
6445         }
6446         res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6447         res->assembly = assembly;
6448
6449         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6450 }
6451
6452
6453
6454 MonoReflectionModule*   
6455 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6456 {
6457         static MonoClass *module_type;
6458         MonoReflectionModule *res;
6459         char* basename;
6460         
6461         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6462         if (!module_type) {
6463                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6464                 if (class == NULL)
6465                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6466                 g_assert (class);
6467                 module_type = class;
6468         }
6469         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6470
6471         res->image = image;
6472         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6473
6474         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6475         basename = g_path_get_basename (image->name);
6476         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6477         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6478         
6479         g_free (basename);
6480
6481         if (image->assembly->image == image) {
6482                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6483         } else {
6484                 int i;
6485                 res->token = 0;
6486                 if (image->assembly->image->modules) {
6487                         for (i = 0; i < image->assembly->image->module_count; i++) {
6488                                 if (image->assembly->image->modules [i] == image)
6489                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6490                         }
6491                         g_assert (res->token);
6492                 }
6493         }
6494
6495         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6496 }
6497
6498 MonoReflectionModule*   
6499 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6500 {
6501         static MonoClass *module_type;
6502         MonoReflectionModule *res;
6503         MonoTableInfo *table;
6504         guint32 cols [MONO_FILE_SIZE];
6505         const char *name;
6506         guint32 i, name_idx;
6507         const char *val;
6508         
6509         if (!module_type) {
6510                 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6511                 if (class == NULL)
6512                         class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6513                 g_assert (class);
6514                 module_type = class;
6515         }
6516         res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6517
6518         table = &image->tables [MONO_TABLE_FILE];
6519         g_assert (table_index < table->rows);
6520         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6521
6522         res->image = NULL;
6523         MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6524         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6525
6526         /* Check whenever the row has a corresponding row in the moduleref table */
6527         table = &image->tables [MONO_TABLE_MODULEREF];
6528         for (i = 0; i < table->rows; ++i) {
6529                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6530                 val = mono_metadata_string_heap (image, name_idx);
6531                 if (strcmp (val, name) == 0)
6532                         res->image = image->modules [i];
6533         }
6534
6535         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6536         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6537         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6538         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6539         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6540
6541         return res;
6542 }
6543
6544 static gboolean
6545 verify_safe_for_managed_space (MonoType *type)
6546 {
6547         switch (type->type) {
6548 #ifdef DEBUG_HARDER
6549         case MONO_TYPE_ARRAY:
6550                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6551         case MONO_TYPE_PTR:
6552                 return verify_safe_for_managed_space (type->data.type);
6553         case MONO_TYPE_SZARRAY:
6554                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6555         case MONO_TYPE_GENERICINST: {
6556                 MonoGenericInst *inst = type->data.generic_class->inst;
6557                 int i;
6558                 if (!inst->is_open)
6559                         break;
6560                 for (i = 0; i < inst->type_argc; ++i)
6561                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6562                                 return FALSE;
6563                 return TRUE;
6564         }
6565 #endif
6566         case MONO_TYPE_VAR:
6567         case MONO_TYPE_MVAR:
6568                 return TRUE;
6569         default:
6570                 return TRUE;
6571         }
6572 }
6573
6574 static MonoType*
6575 mono_type_normalize (MonoType *type)
6576 {
6577         int i;
6578         MonoGenericClass *gclass;
6579         MonoGenericInst *ginst;
6580         MonoClass *gtd;
6581         MonoGenericContainer *gcontainer;
6582         MonoType **argv = NULL;
6583         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6584
6585         if (type->type != MONO_TYPE_GENERICINST)
6586                 return type;
6587
6588         gclass = type->data.generic_class;
6589         ginst = gclass->context.class_inst;
6590         if (!ginst->is_open)
6591                 return type;
6592
6593         gtd = gclass->container_class;
6594         gcontainer = gtd->generic_container;
6595         argv = g_newa (MonoType*, ginst->type_argc);
6596
6597         for (i = 0; i < ginst->type_argc; ++i) {
6598                 MonoType *t = ginst->type_argv [i], *norm;
6599                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6600                         is_denorm_gtd = FALSE;
6601                 norm = mono_type_normalize (t);
6602                 argv [i] = norm;
6603                 if (norm != t)
6604                         requires_rebind = TRUE;
6605         }
6606
6607         if (is_denorm_gtd)
6608                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6609
6610         if (requires_rebind) {
6611                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6612                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6613         }
6614
6615         return type;
6616 }
6617 /*
6618  * mono_type_get_object:
6619  * @domain: an app domain
6620  * @type: a type
6621  *
6622  * Return an System.MonoType object representing the type @type.
6623  */
6624 MonoReflectionType*
6625 mono_type_get_object (MonoDomain *domain, MonoType *type)
6626 {
6627         MonoType *norm_type;
6628         MonoReflectionType *res;
6629         MonoClass *klass = mono_class_from_mono_type (type);
6630
6631         /*we must avoid using @type as it might have come
6632          * from a mono_metadata_type_dup and the caller
6633          * expects that is can be freed.
6634          * Using the right type from 
6635          */
6636         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6637
6638         /* void is very common */
6639         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6640                 return (MonoReflectionType*)domain->typeof_void;
6641
6642         /*
6643          * If the vtable of the given class was already created, we can use
6644          * the MonoType from there and avoid all locking and hash table lookups.
6645          * 
6646          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6647          * that the resulting object is different.   
6648          */
6649         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6650                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6651                 if (vtable && vtable->type)
6652                         return vtable->type;
6653         }
6654
6655         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6656         mono_domain_lock (domain);
6657         if (!domain->type_hash)
6658                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6659                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6660         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6661                 mono_domain_unlock (domain);
6662                 mono_loader_unlock ();
6663                 return res;
6664         }
6665
6666         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6667          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6668          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6669          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6670          * artifact of how generics are encoded and should be transparent to managed code so we
6671          * need to weed out this diference when retrieving managed System.Type objects.
6672          */
6673         norm_type = mono_type_normalize (type);
6674         if (norm_type != type) {
6675                 res = mono_type_get_object (domain, norm_type);
6676                 mono_g_hash_table_insert (domain->type_hash, type, res);
6677                 mono_domain_unlock (domain);
6678                 mono_loader_unlock ();
6679                 return res;
6680         }
6681
6682         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6683         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6684                 g_assert (0);
6685
6686         if (!verify_safe_for_managed_space (type)) {
6687                 mono_domain_unlock (domain);
6688                 mono_loader_unlock ();
6689                 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6690         }
6691
6692         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6693                 gboolean is_type_done = TRUE;
6694                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6695                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6696                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6697                 */
6698                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6699                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6700
6701                         if (gparam->owner && gparam->owner->is_method) {
6702                                 MonoMethod *method = gparam->owner->owner.method;
6703                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6704                                         is_type_done = FALSE;
6705                         } else if (gparam->owner && !gparam->owner->is_method) {
6706                                 MonoClass *klass = gparam->owner->owner.klass;
6707                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6708                                         is_type_done = FALSE;
6709                         }
6710                 } 
6711
6712                 /* g_assert_not_reached (); */
6713                 /* should this be considered an error condition? */
6714                 if (is_type_done && !type->byref) {
6715                         mono_domain_unlock (domain);
6716                         mono_loader_unlock ();
6717                         return mono_class_get_ref_info (klass);
6718                 }
6719         }
6720         /* This is stored in vtables/JITted code so it has to be pinned */
6721         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6722         res->type = type;
6723         mono_g_hash_table_insert (domain->type_hash, type, res);
6724
6725         if (type->type == MONO_TYPE_VOID)
6726                 domain->typeof_void = (MonoObject*)res;
6727
6728         mono_domain_unlock (domain);
6729         mono_loader_unlock ();
6730         return res;
6731 }
6732
6733 /*
6734  * mono_method_get_object:
6735  * @domain: an app domain
6736  * @method: a method
6737  * @refclass: the reflected type (can be NULL)
6738  *
6739  * Return an System.Reflection.MonoMethod object representing the method @method.
6740  */
6741 MonoReflectionMethod*
6742 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6743 {
6744         /*
6745          * We use the same C representation for methods and constructors, but the type 
6746          * name in C# is different.
6747          */
6748         static MonoClass *System_Reflection_MonoMethod = NULL;
6749         static MonoClass *System_Reflection_MonoCMethod = NULL;
6750         static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6751         static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6752         MonoClass *klass;
6753         MonoReflectionMethod *ret;
6754
6755         if (method->is_inflated) {
6756                 MonoReflectionGenericMethod *gret;
6757
6758                 refclass = method->klass;
6759                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6760                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6761                         if (!System_Reflection_MonoGenericCMethod)
6762                                 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6763                         klass = System_Reflection_MonoGenericCMethod;
6764                 } else {
6765                         if (!System_Reflection_MonoGenericMethod)
6766                                 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6767                         klass = System_Reflection_MonoGenericMethod;
6768                 }
6769                 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6770                 gret->method.method = method;
6771                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6772                 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6773                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6774         }
6775
6776         if (!refclass)
6777                 refclass = method->klass;
6778
6779         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6780         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6781                 if (!System_Reflection_MonoCMethod)
6782                         System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6783                 klass = System_Reflection_MonoCMethod;
6784         }
6785         else {
6786                 if (!System_Reflection_MonoMethod)
6787                         System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6788                 klass = System_Reflection_MonoMethod;
6789         }
6790         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6791         ret->method = method;
6792         MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6793         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6794 }
6795
6796 /*
6797  * mono_method_clear_object:
6798  *
6799  *   Clear the cached reflection objects for the dynamic method METHOD.
6800  */
6801 void
6802 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6803 {
6804         MonoClass *klass;
6805         g_assert (method_is_dynamic (method));
6806
6807         klass = method->klass;
6808         while (klass) {
6809                 clear_cached_object (domain, method, klass);
6810                 klass = klass->parent;
6811         }
6812         /* Added by mono_param_get_objects () */
6813         clear_cached_object (domain, &(method->signature), NULL);
6814         klass = method->klass;
6815         while (klass) {
6816                 clear_cached_object (domain, &(method->signature), klass);
6817                 klass = klass->parent;
6818         }
6819 }
6820
6821 /*
6822  * mono_field_get_object:
6823  * @domain: an app domain
6824  * @klass: a type
6825  * @field: a field
6826  *
6827  * Return an System.Reflection.MonoField object representing the field @field
6828  * in class @klass.
6829  */
6830 MonoReflectionField*
6831 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6832 {
6833         MonoReflectionField *res;
6834         static MonoClass *monofield_klass;
6835
6836         CHECK_OBJECT (MonoReflectionField *, field, klass);
6837         if (!monofield_klass)
6838                 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6839         res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6840         res->klass = klass;
6841         res->field = field;
6842         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6843
6844         if (is_field_on_inst (field)) {
6845                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6846                 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6847         } else {
6848                 if (field->type)
6849                         MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6850                 res->attrs = mono_field_get_flags (field);
6851         }
6852         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6853 }
6854
6855 /*
6856  * mono_property_get_object:
6857  * @domain: an app domain
6858  * @klass: a type
6859  * @property: a property
6860  *
6861  * Return an System.Reflection.MonoProperty object representing the property @property
6862  * in class @klass.
6863  */
6864 MonoReflectionProperty*
6865 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6866 {
6867         MonoReflectionProperty *res;
6868         static MonoClass *monoproperty_klass;
6869
6870         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6871         if (!monoproperty_klass)
6872                 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6873         res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6874         res->klass = klass;
6875         res->property = property;
6876         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6877 }
6878
6879 /*
6880  * mono_event_get_object:
6881  * @domain: an app domain
6882  * @klass: a type
6883  * @event: a event
6884  *
6885  * Return an System.Reflection.MonoEvent object representing the event @event
6886  * in class @klass.
6887  */
6888 MonoReflectionEvent*
6889 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6890 {
6891         MonoReflectionEvent *res;
6892         MonoReflectionMonoEvent *mono_event;
6893         static MonoClass *monoevent_klass;
6894
6895         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6896         if (!monoevent_klass)
6897                 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6898         mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6899         mono_event->klass = klass;
6900         mono_event->event = event;
6901         res = (MonoReflectionEvent*)mono_event;
6902         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6903 }
6904
6905 /**
6906  * mono_get_reflection_missing_object:
6907  * @domain: Domain where the object lives
6908  *
6909  * Returns the System.Reflection.Missing.Value singleton object
6910  * (of type System.Reflection.Missing).
6911  *
6912  * Used as the value for ParameterInfo.DefaultValue when Optional
6913  * is present
6914  */
6915 static MonoObject *
6916 mono_get_reflection_missing_object (MonoDomain *domain)
6917 {
6918         MonoObject *obj;
6919         static MonoClassField *missing_value_field = NULL;
6920         
6921         if (!missing_value_field) {
6922                 MonoClass *missing_klass;
6923                 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6924                 mono_class_init (missing_klass);
6925                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6926                 g_assert (missing_value_field);
6927         }
6928         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
6929         g_assert (obj);
6930         return obj;
6931 }
6932
6933 static MonoObject*
6934 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6935 {
6936         if (!*dbnull)
6937                 *dbnull = mono_get_dbnull_object (domain);
6938         return *dbnull;
6939 }
6940
6941 static MonoObject*
6942 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6943 {
6944         if (!*reflection_missing)
6945                 *reflection_missing = mono_get_reflection_missing_object (domain);
6946         return *reflection_missing;
6947 }
6948
6949 /*
6950  * mono_param_get_objects:
6951  * @domain: an app domain
6952  * @method: a method
6953  *
6954  * Return an System.Reflection.ParameterInfo array object representing the parameters
6955  * in the method @method.
6956  */
6957 MonoArray*
6958 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6959 {
6960         static MonoClass *System_Reflection_ParameterInfo;
6961         static MonoClass *System_Reflection_ParameterInfo_array;
6962         MonoError error;
6963         MonoArray *res = NULL;
6964         MonoReflectionMethod *member = NULL;
6965         MonoReflectionParameter *param = NULL;
6966         char **names, **blobs = NULL;
6967         guint32 *types = NULL;
6968         MonoType *type = NULL;
6969         MonoObject *dbnull = NULL;
6970         MonoObject *missing = NULL;
6971         MonoMarshalSpec **mspecs;
6972         MonoMethodSignature *sig;
6973         MonoVTable *pinfo_vtable;
6974         int i;
6975
6976         if (!System_Reflection_ParameterInfo_array) {
6977                 MonoClass *klass;
6978
6979                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
6980                 if (!klass)
6981                         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6982
6983                 mono_memory_barrier ();
6984                 System_Reflection_ParameterInfo = klass; 
6985
6986         
6987                 klass = mono_array_class_get (klass, 1);
6988                 mono_memory_barrier ();
6989                 System_Reflection_ParameterInfo_array = klass;
6990         }
6991
6992         sig = mono_method_signature_checked (method, &error);
6993         if (!mono_error_ok (&error))
6994                 mono_error_raise_exception (&error);
6995
6996         if (!sig->param_count)
6997                 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6998
6999         /* Note: the cache is based on the address of the signature into the method
7000          * since we already cache MethodInfos with the method as keys.
7001          */
7002         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7003
7004         member = mono_method_get_object (domain, method, refclass);
7005         names = g_new (char *, sig->param_count);
7006         mono_method_get_param_names (method, (const char **) names);
7007
7008         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7009         mono_method_get_marshal_info (method, mspecs);
7010
7011         res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
7012         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7013         for (i = 0; i < sig->param_count; ++i) {
7014                 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
7015                 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
7016                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7017                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7018                 param->PositionImpl = i;
7019                 param->AttrsImpl = sig->params [i]->attrs;
7020
7021                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7022                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7023                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7024                         else
7025                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7026                 } else {
7027
7028                         if (!blobs) {
7029                                 blobs = g_new0 (char *, sig->param_count);
7030                                 types = g_new0 (guint32, sig->param_count);
7031                                 get_default_param_value_blobs (method, blobs, types); 
7032                         }
7033
7034                         /* Build MonoType for the type from the Constant Table */
7035                         if (!type)
7036                                 type = g_new0 (MonoType, 1);
7037                         type->type = types [i];
7038                         type->data.klass = NULL;
7039                         if (types [i] == MONO_TYPE_CLASS)
7040                                 type->data.klass = mono_defaults.object_class;
7041                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7042                                 /* For enums, types [i] contains the base type */
7043
7044                                         type->type = MONO_TYPE_VALUETYPE;
7045                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7046                         } else
7047                                 type->data.klass = mono_class_from_mono_type (type);
7048
7049                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7050
7051                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7052                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7053                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7054                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7055                                 else
7056                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7057                         }
7058                         
7059                 }
7060
7061                 if (mspecs [i + 1])
7062                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
7063                 
7064                 mono_array_setref (res, i, param);
7065         }
7066         g_free (names);
7067         g_free (blobs);
7068         g_free (types);
7069         g_free (type);
7070
7071         for (i = mono_method_signature (method)->param_count; i >= 0; i--)
7072                 if (mspecs [i])
7073                         mono_metadata_free_marshal_spec (mspecs [i]);
7074         g_free (mspecs);
7075         
7076         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7077 }
7078
7079 MonoArray*
7080 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7081 {
7082         return mono_param_get_objects_internal (domain, method, NULL);
7083 }
7084
7085 /*
7086  * mono_method_body_get_object:
7087  * @domain: an app domain
7088  * @method: a method
7089  *
7090  * Return an System.Reflection.MethodBody object representing the method @method.
7091  */
7092 MonoReflectionMethodBody*
7093 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7094 {
7095         static MonoClass *System_Reflection_MethodBody = NULL;
7096         static MonoClass *System_Reflection_LocalVariableInfo = NULL;
7097         static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
7098         MonoReflectionMethodBody *ret;
7099         MonoMethodHeader *header;
7100         MonoImage *image;
7101         guint32 method_rva, local_var_sig_token;
7102     char *ptr;
7103         unsigned char format, flags;
7104         int i;
7105
7106         /* for compatibility with .net */
7107     if (method_is_dynamic (method))
7108         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7109
7110         if (!System_Reflection_MethodBody)
7111                 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
7112         if (!System_Reflection_LocalVariableInfo)
7113                 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
7114         if (!System_Reflection_ExceptionHandlingClause)
7115                 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
7116
7117         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7118
7119         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7120                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7121             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7122             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7123                 return NULL;
7124
7125         image = method->klass->image;
7126         header = mono_method_get_header (method);
7127
7128         if (!image_is_dynamic (image)) {
7129                 /* Obtain local vars signature token */
7130                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7131                 ptr = mono_image_rva_map (image, method_rva);
7132                 flags = *(const unsigned char *) ptr;
7133                 format = flags & METHOD_HEADER_FORMAT_MASK;
7134                 switch (format){
7135                 case METHOD_HEADER_TINY_FORMAT:
7136                         local_var_sig_token = 0;
7137                         break;
7138                 case METHOD_HEADER_FAT_FORMAT:
7139                         ptr += 2;
7140                         ptr += 2;
7141                         ptr += 4;
7142                         local_var_sig_token = read32 (ptr);
7143                         break;
7144                 default:
7145                         g_assert_not_reached ();
7146                 }
7147         } else
7148                 local_var_sig_token = 0; //FIXME
7149
7150         ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
7151
7152         ret->init_locals = header->init_locals;
7153         ret->max_stack = header->max_stack;
7154         ret->local_var_sig_token = local_var_sig_token;
7155         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7156         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7157
7158         /* Locals */
7159         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
7160         for (i = 0; i < header->num_locals; ++i) {
7161                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
7162                 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
7163                 info->is_pinned = header->locals [i]->pinned;
7164                 info->local_index = i;
7165                 mono_array_setref (ret->locals, i, info);
7166         }
7167
7168         /* Exceptions */
7169         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
7170         for (i = 0; i < header->num_clauses; ++i) {
7171                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
7172                 MonoExceptionClause *clause = &header->clauses [i];
7173
7174                 info->flags = clause->flags;
7175                 info->try_offset = clause->try_offset;
7176                 info->try_length = clause->try_len;
7177                 info->handler_offset = clause->handler_offset;
7178                 info->handler_length = clause->handler_len;
7179                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7180                         info->filter_offset = clause->data.filter_offset;
7181                 else if (clause->data.catch_class)
7182                         MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
7183
7184                 mono_array_setref (ret->clauses, i, info);
7185         }
7186
7187         mono_metadata_free_mh (header);
7188         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7189         return ret;
7190 }
7191
7192 /**
7193  * mono_get_dbnull_object:
7194  * @domain: Domain where the object lives
7195  *
7196  * Returns the System.DBNull.Value singleton object
7197  *
7198  * Used as the value for ParameterInfo.DefaultValue 
7199  */
7200 MonoObject *
7201 mono_get_dbnull_object (MonoDomain *domain)
7202 {
7203         MonoObject *obj;
7204         static MonoClassField *dbnull_value_field = NULL;
7205         
7206         if (!dbnull_value_field) {
7207                 MonoClass *dbnull_klass;
7208                 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7209                 mono_class_init (dbnull_klass);
7210                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7211                 g_assert (dbnull_value_field);
7212         }
7213         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7214         g_assert (obj);
7215         return obj;
7216 }
7217
7218 static void
7219 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7220 {
7221         guint32 param_index, i, lastp, crow = 0;
7222         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7223         gint32 idx;
7224
7225         MonoClass *klass = method->klass;
7226         MonoImage *image = klass->image;
7227         MonoMethodSignature *methodsig = mono_method_signature (method);
7228
7229         MonoTableInfo *constt;
7230         MonoTableInfo *methodt;
7231         MonoTableInfo *paramt;
7232
7233         if (!methodsig->param_count)
7234                 return;
7235
7236         mono_class_init (klass);
7237
7238         if (image_is_dynamic (klass->image)) {
7239                 MonoReflectionMethodAux *aux;
7240                 if (method->is_inflated)
7241                         method = ((MonoMethodInflated*)method)->declaring;
7242                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7243                 if (aux && aux->param_defaults) {
7244                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7245                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7246                 }
7247                 return;
7248         }
7249
7250         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7251         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7252         constt = &image->tables [MONO_TABLE_CONSTANT];
7253
7254         idx = mono_method_get_index (method) - 1;
7255         g_assert (idx != -1);
7256
7257         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7258         if (idx + 1 < methodt->rows)
7259                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7260         else
7261                 lastp = paramt->rows + 1;
7262
7263         for (i = param_index; i < lastp; ++i) {
7264                 guint32 paramseq;
7265
7266                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7267                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7268
7269                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7270                         continue;
7271
7272                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7273                 if (!crow) {
7274                         continue;
7275                 }
7276         
7277                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7278                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7279                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7280         }
7281
7282         return;
7283 }
7284
7285 MonoObject *
7286 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7287 {
7288         void *retval;
7289         MonoClass *klass;
7290         MonoObject *object;
7291         MonoType *basetype = type;
7292
7293         if (!blob)
7294                 return NULL;
7295         
7296         klass = mono_class_from_mono_type (type);
7297         if (klass->valuetype) {
7298                 object = mono_object_new (domain, klass);
7299                 retval = ((gchar *) object + sizeof (MonoObject));
7300                 if (klass->enumtype)
7301                         basetype = mono_class_enum_basetype (klass);
7302         } else {
7303                 retval = &object;
7304         }
7305                         
7306         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7307                 return object;
7308         else
7309                 return NULL;
7310 }
7311
7312 static int
7313 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7314         int found_sep;
7315         char *s;
7316         gboolean quoted = FALSE;
7317
7318         memset (assembly, 0, sizeof (MonoAssemblyName));
7319         assembly->culture = "";
7320         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7321
7322         if (*p == '"') {
7323                 quoted = TRUE;
7324                 p++;
7325         }
7326         assembly->name = p;
7327         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7328                 p++;
7329         if (quoted) {
7330                 if (*p != '"')
7331                         return 1;
7332                 *p = 0;
7333                 p++;
7334         }
7335         if (*p != ',')
7336                 return 1;
7337         *p = 0;
7338         /* Remove trailing whitespace */
7339         s = p - 1;
7340         while (*s && g_ascii_isspace (*s))
7341                 *s-- = 0;
7342         p ++;
7343         while (g_ascii_isspace (*p))
7344                 p++;
7345         while (*p) {
7346                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7347                         p += 8;
7348                         assembly->major = strtoul (p, &s, 10);
7349                         if (s == p || *s != '.')
7350                                 return 1;
7351                         p = ++s;
7352                         assembly->minor = strtoul (p, &s, 10);
7353                         if (s == p || *s != '.')
7354                                 return 1;
7355                         p = ++s;
7356                         assembly->build = strtoul (p, &s, 10);
7357                         if (s == p || *s != '.')
7358                                 return 1;
7359                         p = ++s;
7360                         assembly->revision = strtoul (p, &s, 10);
7361                         if (s == p)
7362                                 return 1;
7363                         p = s;
7364                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7365                         p += 8;
7366                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7367                                 assembly->culture = "";
7368                                 p += 7;
7369                         } else {
7370                                 assembly->culture = p;
7371                                 while (*p && *p != ',') {
7372                                         p++;
7373                                 }
7374                         }
7375                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7376                         p += 15;
7377                         if (strncmp (p, "null", 4) == 0) {
7378                                 p += 4;
7379                         } else {
7380                                 int len;
7381                                 gchar *start = p;
7382                                 while (*p && *p != ',') {
7383                                         p++;
7384                                 }
7385                                 len = (p - start + 1);
7386                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7387                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7388                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7389                         }
7390                 } else {
7391                         while (*p && *p != ',')
7392                                 p++;
7393                 }
7394                 found_sep = 0;
7395                 while (g_ascii_isspace (*p) || *p == ',') {
7396                         *p++ = 0;
7397                         found_sep = 1;
7398                         continue;
7399                 }
7400                 /* failed */
7401                 if (!found_sep)
7402                         return 1;
7403         }
7404
7405         return 0;
7406 }
7407
7408 /*
7409  * mono_reflection_parse_type:
7410  * @name: type name
7411  *
7412  * Parse a type name as accepted by the GetType () method and output the info
7413  * extracted in the info structure.
7414  * the name param will be mangled, so, make a copy before passing it to this function.
7415  * The fields in info will be valid until the memory pointed to by name is valid.
7416  *
7417  * See also mono_type_get_name () below.
7418  *
7419  * Returns: 0 on parse error.
7420  */
7421 static int
7422 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7423                              MonoTypeNameParse *info)
7424 {
7425         char *start, *p, *w, *last_point, *startn;
7426         int in_modifiers = 0;
7427         int isbyref = 0, rank = 0, isptr = 0;
7428
7429         start = p = w = name;
7430
7431         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7432         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7433         info->name = info->name_space = NULL;
7434         info->nested = NULL;
7435         info->modifiers = NULL;
7436         info->type_arguments = NULL;
7437
7438         /* last_point separates the namespace from the name */
7439         last_point = NULL;
7440         /* Skips spaces */
7441         while (*p == ' ') p++, start++, w++, name++;
7442
7443         while (*p) {
7444                 switch (*p) {
7445                 case '+':
7446                         *p = 0; /* NULL terminate the name */
7447                         startn = p + 1;
7448                         info->nested = g_list_append (info->nested, startn);
7449                         /* we have parsed the nesting namespace + name */
7450                         if (info->name)
7451                                 break;
7452                         if (last_point) {
7453                                 info->name_space = start;
7454                                 *last_point = 0;
7455                                 info->name = last_point + 1;
7456                         } else {
7457                                 info->name_space = (char *)"";
7458                                 info->name = start;
7459                         }
7460                         break;
7461                 case '.':
7462                         last_point = p;
7463                         break;
7464                 case '\\':
7465                         ++p;
7466                         break;
7467                 case '&':
7468                 case '*':
7469                 case '[':
7470                 case ',':
7471                 case ']':
7472                         in_modifiers = 1;
7473                         break;
7474                 default:
7475                         break;
7476                 }
7477                 if (in_modifiers)
7478                         break;
7479                 // *w++ = *p++;
7480                 p++;
7481         }
7482         
7483         if (!info->name) {
7484                 if (last_point) {
7485                         info->name_space = start;
7486                         *last_point = 0;
7487                         info->name = last_point + 1;
7488                 } else {
7489                         info->name_space = (char *)"";
7490                         info->name = start;
7491                 }
7492         }
7493         while (*p) {
7494                 switch (*p) {
7495                 case '&':
7496                         if (isbyref) /* only one level allowed by the spec */
7497                                 return 0;
7498                         isbyref = 1;
7499                         isptr = 0;
7500                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7501                         *p++ = 0;
7502                         break;
7503                 case '*':
7504                         if (isbyref) /* pointer to ref not okay */
7505                                 return 0;
7506                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7507                         isptr = 1;
7508                         *p++ = 0;
7509                         break;
7510                 case '[':
7511                         if (isbyref) /* array of ref and generic ref are not okay */
7512                                 return 0;
7513                         //Decide if it's an array of a generic argument list
7514                         *p++ = 0;
7515
7516                         if (!*p) //XXX test
7517                                 return 0;
7518                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7519                                 isptr = 0;
7520                                 rank = 1;
7521                                 while (*p) {
7522                                         if (*p == ']')
7523                                                 break;
7524                                         if (*p == ',')
7525                                                 rank++;
7526                                         else if (*p == '*') /* '*' means unknown lower bound */
7527                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7528                                         else
7529                                                 return 0;
7530                                         ++p;
7531                                 }
7532                                 if (*p++ != ']')
7533                                         return 0;
7534                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7535                         } else {
7536                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7537                                         return 0;
7538                                 isptr = 0;
7539                                 info->type_arguments = g_ptr_array_new ();
7540                                 while (*p) {
7541                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7542                                         gboolean fqname = FALSE;
7543
7544                                         g_ptr_array_add (info->type_arguments, subinfo);
7545
7546                                         while (*p == ' ') p++;
7547                                         if (*p == '[') {
7548                                                 p++;
7549                                                 fqname = TRUE;
7550                                         }
7551
7552                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7553                                                 return 0;
7554
7555                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7556                                         if (fqname && (*p != ']')) {
7557                                                 char *aname;
7558
7559                                                 if (*p != ',')
7560                                                         return 0;
7561                                                 *p++ = 0;
7562
7563                                                 aname = p;
7564                                                 while (*p && (*p != ']'))
7565                                                         p++;
7566
7567                                                 if (*p != ']')
7568                                                         return 0;
7569
7570                                                 *p++ = 0;
7571                                                 while (*aname) {
7572                                                         if (g_ascii_isspace (*aname)) {
7573                                                                 ++aname;
7574                                                                 continue;
7575                                                         }
7576                                                         break;
7577                                                 }
7578                                                 if (!*aname ||
7579                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7580                                                         return 0;
7581                                         } else if (fqname && (*p == ']')) {
7582                                                 *p++ = 0;
7583                                         }
7584                                         if (*p == ']') {
7585                                                 *p++ = 0;
7586                                                 break;
7587                                         } else if (!*p) {
7588                                                 return 0;
7589                                         }
7590                                         *p++ = 0;
7591                                 }
7592                         }
7593                         break;
7594                 case ']':
7595                         if (is_recursed)
7596                                 goto end;
7597                         return 0;
7598                 case ',':
7599                         if (is_recursed)
7600                                 goto end;
7601                         *p++ = 0;
7602                         while (*p) {
7603                                 if (g_ascii_isspace (*p)) {
7604                                         ++p;
7605                                         continue;
7606                                 }
7607                                 break;
7608                         }
7609                         if (!*p)
7610                                 return 0; /* missing assembly name */
7611                         if (!assembly_name_to_aname (&info->assembly, p))
7612                                 return 0;
7613                         break;
7614                 default:
7615                         return 0;
7616                 }
7617                 if (info->assembly.name)
7618                         break;
7619         }
7620         // *w = 0; /* terminate class name */
7621  end:
7622         if (!info->name || !*info->name)
7623                 return 0;
7624         if (endptr)
7625                 *endptr = p;
7626         /* add other consistency checks */
7627         return 1;
7628 }
7629
7630 int
7631 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7632 {
7633         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7634 }
7635
7636 static MonoType*
7637 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7638 {
7639         gboolean type_resolve = FALSE;
7640         MonoType *type;
7641         MonoImage *rootimage = image;
7642
7643         if (info->assembly.name) {
7644                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7645                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7646                         /* 
7647                          * This could happen in the AOT compiler case when the search hook is not
7648                          * installed.
7649                          */
7650                         assembly = image->assembly;
7651                 if (!assembly) {
7652                         /* then we must load the assembly ourselve - see #60439 */
7653                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7654                         if (!assembly)
7655                                 return NULL;
7656                 }
7657                 image = assembly->image;
7658         } else if (!image) {
7659                 image = mono_defaults.corlib;
7660         }
7661
7662         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7663         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7664                 image = mono_defaults.corlib;
7665                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7666         }
7667
7668         return type;
7669 }
7670
7671 static MonoType*
7672 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7673 {
7674         MonoClass *klass;
7675         GList *mod;
7676         int modval;
7677         gboolean bounded = FALSE;
7678         
7679         if (!image)
7680                 image = mono_defaults.corlib;
7681
7682         if (!rootimage)
7683                 rootimage = mono_defaults.corlib;
7684
7685         if (ignorecase) {
7686                 MonoError error;
7687                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7688                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7689         } else {
7690                 klass = mono_class_from_name (image, info->name_space, info->name);
7691         }
7692         if (!klass)
7693                 return NULL;
7694         for (mod = info->nested; mod; mod = mod->next) {
7695                 gpointer iter = NULL;
7696                 MonoClass *parent;
7697
7698                 parent = klass;
7699                 mono_class_init (parent);
7700
7701                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7702                         char *lastp;
7703                         char *nested_name, *nested_nspace;
7704                         gboolean match = TRUE;
7705
7706                         lastp = strrchr (mod->data, '.');
7707                         if (lastp) {
7708                                 /* Nested classes can have namespaces */
7709                                 int nspace_len;
7710
7711                                 nested_name = g_strdup (lastp + 1);
7712                                 nspace_len = lastp - (char*)mod->data;
7713                                 nested_nspace = g_malloc (nspace_len + 1);
7714                                 memcpy (nested_nspace, mod->data, nspace_len);
7715                                 nested_nspace [nspace_len] = '\0';
7716
7717                         } else {
7718                                 nested_name = mod->data;
7719                                 nested_nspace = NULL;
7720                         }
7721
7722                         if (nested_nspace) {
7723                                 if (ignorecase) {
7724                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7725                                                 match = FALSE;
7726                                 } else {
7727                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7728                                                 match = FALSE;
7729                                 }
7730                         }
7731                         if (match) {
7732                                 if (ignorecase) {
7733                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7734                                                 match = FALSE;
7735                                 } else {
7736                                         if (strcmp (klass->name, nested_name) != 0)
7737                                                 match = FALSE;
7738                                 }
7739                         }
7740                         if (lastp) {
7741                                 g_free (nested_name);
7742                                 g_free (nested_nspace);
7743                         }
7744                         if (match)
7745                                 break;
7746                 }
7747
7748                 if (!klass)
7749                         break;
7750         }
7751         if (!klass)
7752                 return NULL;
7753
7754         if (info->type_arguments) {
7755                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7756                 MonoReflectionType *the_type;
7757                 MonoType *instance;
7758                 int i;
7759
7760                 for (i = 0; i < info->type_arguments->len; i++) {
7761                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7762
7763                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7764                         if (!type_args [i]) {
7765                                 g_free (type_args);
7766                                 return NULL;
7767                         }
7768                 }
7769
7770                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7771
7772                 instance = mono_reflection_bind_generic_parameters (
7773                         the_type, info->type_arguments->len, type_args);
7774
7775                 g_free (type_args);
7776                 if (!instance)
7777                         return NULL;
7778
7779                 klass = mono_class_from_mono_type (instance);
7780         }
7781
7782         for (mod = info->modifiers; mod; mod = mod->next) {
7783                 modval = GPOINTER_TO_UINT (mod->data);
7784                 if (!modval) { /* byref: must be last modifier */
7785                         return &klass->this_arg;
7786                 } else if (modval == -1) {
7787                         klass = mono_ptr_class_get (&klass->byval_arg);
7788                 } else if (modval == -2) {
7789                         bounded = TRUE;
7790                 } else { /* array rank */
7791                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7792                 }
7793         }
7794
7795         return &klass->byval_arg;
7796 }
7797
7798 /*
7799  * mono_reflection_get_type:
7800  * @image: a metadata context
7801  * @info: type description structure
7802  * @ignorecase: flag for case-insensitive string compares
7803  * @type_resolve: whenever type resolve was already tried
7804  *
7805  * Build a MonoType from the type description in @info.
7806  * 
7807  */
7808
7809 MonoType*
7810 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7811         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7812 }
7813
7814 static MonoType*
7815 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7816 {
7817         MonoReflectionAssemblyBuilder *abuilder;
7818         MonoType *type;
7819         int i;
7820
7821         g_assert (assembly_is_dynamic (assembly));
7822         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7823
7824         /* Enumerate all modules */
7825
7826         type = NULL;
7827         if (abuilder->modules) {
7828                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7829                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7830                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7831                         if (type)
7832                                 break;
7833                 }
7834         }
7835
7836         if (!type && abuilder->loaded_modules) {
7837                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7838                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7839                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7840                         if (type)
7841                                 break;
7842                 }
7843         }
7844
7845         return type;
7846 }
7847         
7848 MonoType*
7849 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7850 {
7851         MonoType *type;
7852         MonoReflectionAssembly *assembly;
7853         GString *fullName;
7854         GList *mod;
7855
7856         if (image && image_is_dynamic (image))
7857                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7858         else
7859                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7860         if (type)
7861                 return type;
7862         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7863                 return NULL;
7864
7865         if (type_resolve) {
7866                 if (*type_resolve) 
7867                         return NULL;
7868                 else
7869                         *type_resolve = TRUE;
7870         }
7871         
7872         /* Reconstruct the type name */
7873         fullName = g_string_new ("");
7874         if (info->name_space && (info->name_space [0] != '\0'))
7875                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7876         else
7877                 g_string_printf (fullName, "%s", info->name);
7878         for (mod = info->nested; mod; mod = mod->next)
7879                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7880
7881         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7882         if (assembly) {
7883                 if (assembly_is_dynamic (assembly->assembly))
7884                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7885                 else
7886                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7887                                                                                                           info, ignorecase);
7888         }
7889         g_string_free (fullName, TRUE);
7890         return type;
7891 }
7892
7893 void
7894 mono_reflection_free_type_info (MonoTypeNameParse *info)
7895 {
7896         g_list_free (info->modifiers);
7897         g_list_free (info->nested);
7898
7899         if (info->type_arguments) {
7900                 int i;
7901
7902                 for (i = 0; i < info->type_arguments->len; i++) {
7903                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7904
7905                         mono_reflection_free_type_info (subinfo);
7906                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7907                         g_free (subinfo);
7908                 }
7909
7910                 g_ptr_array_free (info->type_arguments, TRUE);
7911         }
7912 }
7913
7914 /*
7915  * mono_reflection_type_from_name:
7916  * @name: type name.
7917  * @image: a metadata context (can be NULL).
7918  *
7919  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7920  * it defaults to get the type from @image or, if @image is NULL or loading
7921  * from it fails, uses corlib.
7922  * 
7923  */
7924 MonoType*
7925 mono_reflection_type_from_name (char *name, MonoImage *image)
7926 {
7927         MonoType *type = NULL;
7928         MonoTypeNameParse info;
7929         char *tmp;
7930
7931         /* Make a copy since parse_type modifies its argument */
7932         tmp = g_strdup (name);
7933         
7934         /*g_print ("requested type %s\n", str);*/
7935         if (mono_reflection_parse_type (tmp, &info)) {
7936                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7937         }
7938
7939         g_free (tmp);
7940         mono_reflection_free_type_info (&info);
7941         return type;
7942 }
7943
7944 /*
7945  * mono_reflection_get_token:
7946  *
7947  *   Return the metadata token of OBJ which should be an object
7948  * representing a metadata element.
7949  */
7950 guint32
7951 mono_reflection_get_token (MonoObject *obj)
7952 {
7953         MonoClass *klass;
7954         guint32 token = 0;
7955
7956         klass = obj->vtable->klass;
7957
7958         if (strcmp (klass->name, "MethodBuilder") == 0) {
7959                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7960
7961                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7962         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7963                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7964
7965                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7966         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7967                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7968
7969                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7970         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7971                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7972                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7973         } else if (strcmp (klass->name, "MonoType") == 0) {
7974                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7975                 MonoClass *mc = mono_class_from_mono_type (type);
7976                 if (!mono_class_init (mc))
7977                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7978
7979                 token = mc->type_token;
7980         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7981                    strcmp (klass->name, "MonoMethod") == 0 ||
7982                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7983                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7984                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7985                 if (m->method->is_inflated) {
7986                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7987                         return inflated->declaring->token;
7988                 } else {
7989                         token = m->method->token;
7990                 }
7991         } else if (strcmp (klass->name, "MonoField") == 0) {
7992                 MonoReflectionField *f = (MonoReflectionField*)obj;
7993
7994                 if (is_field_on_inst (f->field)) {
7995                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7996
7997                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
7998                                 int field_index = f->field - dgclass->fields;
7999                                 MonoObject *obj;
8000
8001                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8002                                 obj = dgclass->field_objects [field_index];
8003                                 return mono_reflection_get_token (obj);
8004                         }
8005                 }
8006                 token = mono_class_get_field_token (f->field);
8007         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8008                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8009
8010                 token = mono_class_get_property_token (p->property);
8011         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8012                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8013
8014                 token = mono_class_get_event_token (p->event);
8015         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8016                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8017                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8018                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8019
8020                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8021         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8022                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8023
8024                 token = m->token;
8025         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8026                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8027         } else {
8028                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8029                 MonoException *ex = mono_get_exception_not_implemented (msg);
8030                 g_free (msg);
8031                 mono_raise_exception (ex);
8032         }
8033
8034         return token;
8035 }
8036
8037 static MonoClass*
8038 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8039 {
8040         char *n;
8041         MonoType *t;
8042         int slen = mono_metadata_decode_value (p, &p);
8043
8044         mono_error_init (error);
8045
8046         n = g_memdup (p, slen + 1);
8047         n [slen] = 0;
8048         t = mono_reflection_type_from_name (n, image);
8049         if (!t) {
8050                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8051                 /* We don't free n, it's consumed by mono_error */
8052                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8053                 return NULL;
8054         }
8055         g_free (n);
8056         p += slen;
8057         *end = p;
8058         return mono_class_from_mono_type (t);
8059 }
8060
8061 static void*
8062 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8063 {
8064         int slen, type = t->type;
8065         MonoClass *tklass = t->data.klass;
8066
8067         mono_error_init (error);
8068
8069 handle_enum:
8070         switch (type) {
8071         case MONO_TYPE_U1:
8072         case MONO_TYPE_I1:
8073         case MONO_TYPE_BOOLEAN: {
8074                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
8075                 *bval = *p;
8076                 *end = p + 1;
8077                 return bval;
8078         }
8079         case MONO_TYPE_CHAR:
8080         case MONO_TYPE_U2:
8081         case MONO_TYPE_I2: {
8082                 guint16 *val = g_malloc (sizeof (guint16));
8083                 *val = read16 (p);
8084                 *end = p + 2;
8085                 return val;
8086         }
8087 #if SIZEOF_VOID_P == 4
8088         case MONO_TYPE_U:
8089         case MONO_TYPE_I:
8090 #endif
8091         case MONO_TYPE_R4:
8092         case MONO_TYPE_U4:
8093         case MONO_TYPE_I4: {
8094                 guint32 *val = g_malloc (sizeof (guint32));
8095                 *val = read32 (p);
8096                 *end = p + 4;
8097                 return val;
8098         }
8099 #if SIZEOF_VOID_P == 8
8100         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8101         case MONO_TYPE_I:
8102 #endif
8103         case MONO_TYPE_U8:
8104         case MONO_TYPE_I8: {
8105                 guint64 *val = g_malloc (sizeof (guint64));
8106                 *val = read64 (p);
8107                 *end = p + 8;
8108                 return val;
8109         }
8110         case MONO_TYPE_R8: {
8111                 double *val = g_malloc (sizeof (double));
8112                 readr8 (p, val);
8113                 *end = p + 8;
8114                 return val;
8115         }
8116         case MONO_TYPE_VALUETYPE:
8117                 if (t->data.klass->enumtype) {
8118                         type = mono_class_enum_basetype (t->data.klass)->type;
8119                         goto handle_enum;
8120                 } else {
8121                         MonoClass *k =  t->data.klass;
8122                         
8123                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8124                                 guint64 *val = g_malloc (sizeof (guint64));
8125                                 *val = read64 (p);
8126                                 *end = p + 8;
8127                                 return val;
8128                         }
8129                 }
8130                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8131                 break;
8132                 
8133         case MONO_TYPE_STRING:
8134                 if (*p == (char)0xFF) {
8135                         *end = p + 1;
8136                         return NULL;
8137                 }
8138                 slen = mono_metadata_decode_value (p, &p);
8139                 *end = p + slen;
8140                 return mono_string_new_len (mono_domain_get (), p, slen);
8141         case MONO_TYPE_CLASS: {
8142                 char *n;
8143                 MonoType *t;
8144                 if (*p == (char)0xFF) {
8145                         *end = p + 1;
8146                         return NULL;
8147                 }
8148 handle_type:
8149                 slen = mono_metadata_decode_value (p, &p);
8150                 n = g_memdup (p, slen + 1);
8151                 n [slen] = 0;
8152                 t = mono_reflection_type_from_name (n, image);
8153                 if (!t) {
8154                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8155                         /* We don't free n, it's consumed by mono_error */
8156                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8157                         return NULL;
8158                 }
8159                 g_free (n);
8160                 *end = p + slen;
8161                 return mono_type_get_object (mono_domain_get (), t);
8162         }
8163         case MONO_TYPE_OBJECT: {
8164                 char subt = *p++;
8165                 MonoObject *obj;
8166                 MonoClass *subc = NULL;
8167                 void *val;
8168
8169                 if (subt == 0x50) {
8170                         goto handle_type;
8171                 } else if (subt == 0x0E) {
8172                         type = MONO_TYPE_STRING;
8173                         goto handle_enum;
8174                 } else if (subt == 0x1D) {
8175                         MonoType simple_type = {{0}};
8176                         int etype = *p;
8177                         p ++;
8178
8179                         type = MONO_TYPE_SZARRAY;
8180                         if (etype == 0x50) {
8181                                 tklass = mono_defaults.systemtype_class;
8182                         } else if (etype == 0x55) {
8183                                 tklass = load_cattr_enum_type (image, p, &p, error);
8184                                 if (!mono_error_ok (error))
8185                                         return NULL;
8186                         } else {
8187                                 if (etype == 0x51)
8188                                         /* See Partition II, Appendix B3 */
8189                                         etype = MONO_TYPE_OBJECT;
8190                                 simple_type.type = etype;
8191                                 tklass = mono_class_from_mono_type (&simple_type);
8192                         }
8193                         goto handle_enum;
8194                 } else if (subt == 0x55) {
8195                         char *n;
8196                         MonoType *t;
8197                         slen = mono_metadata_decode_value (p, &p);
8198                         n = g_memdup (p, slen + 1);
8199                         n [slen] = 0;
8200                         t = mono_reflection_type_from_name (n, image);
8201                         if (!t) {
8202                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8203                                 /* We don't free n, it's consumed by mono_error */
8204                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8205                                 return NULL;
8206                         }
8207                         g_free (n);
8208                         p += slen;
8209                         subc = mono_class_from_mono_type (t);
8210                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8211                         MonoType simple_type = {{0}};
8212                         simple_type.type = subt;
8213                         subc = mono_class_from_mono_type (&simple_type);
8214                 } else {
8215                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8216                 }
8217                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8218                 obj = NULL;
8219                 if (mono_error_ok (error)) {
8220                         obj = mono_object_new (mono_domain_get (), subc);
8221                         g_assert (!subc->has_references);
8222                         mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8223                 }
8224
8225                 g_free (val);
8226                 return obj;
8227         }
8228         case MONO_TYPE_SZARRAY: {
8229                 MonoArray *arr;
8230                 guint32 i, alen, basetype;
8231                 alen = read32 (p);
8232                 p += 4;
8233                 if (alen == 0xffffffff) {
8234                         *end = p;
8235                         return NULL;
8236                 }
8237                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8238                 basetype = tklass->byval_arg.type;
8239                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8240                         basetype = mono_class_enum_basetype (tklass)->type;
8241                 switch (basetype)
8242                 {
8243                         case MONO_TYPE_U1:
8244                         case MONO_TYPE_I1:
8245                         case MONO_TYPE_BOOLEAN:
8246                                 for (i = 0; i < alen; i++) {
8247                                         MonoBoolean val = *p++;
8248                                         mono_array_set (arr, MonoBoolean, i, val);
8249                                 }
8250                                 break;
8251                         case MONO_TYPE_CHAR:
8252                         case MONO_TYPE_U2:
8253                         case MONO_TYPE_I2:
8254                                 for (i = 0; i < alen; i++) {
8255                                         guint16 val = read16 (p);
8256                                         mono_array_set (arr, guint16, i, val);
8257                                         p += 2;
8258                                 }
8259                                 break;
8260                         case MONO_TYPE_R4:
8261                         case MONO_TYPE_U4:
8262                         case MONO_TYPE_I4:
8263                                 for (i = 0; i < alen; i++) {
8264                                         guint32 val = read32 (p);
8265                                         mono_array_set (arr, guint32, i, val);
8266                                         p += 4;
8267                                 }
8268                                 break;
8269                         case MONO_TYPE_R8:
8270                                 for (i = 0; i < alen; i++) {
8271                                         double val;
8272                                         readr8 (p, &val);
8273                                         mono_array_set (arr, double, i, val);
8274                                         p += 8;
8275                                 }
8276                                 break;
8277                         case MONO_TYPE_U8:
8278                         case MONO_TYPE_I8:
8279                                 for (i = 0; i < alen; i++) {
8280                                         guint64 val = read64 (p);
8281                                         mono_array_set (arr, guint64, i, val);
8282                                         p += 8;
8283                                 }
8284                                 break;
8285                         case MONO_TYPE_CLASS:
8286                         case MONO_TYPE_OBJECT:
8287                         case MONO_TYPE_STRING:
8288                         case MONO_TYPE_SZARRAY:
8289                                 for (i = 0; i < alen; i++) {
8290                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8291                                         if (!mono_error_ok (error))
8292                                                 return NULL;
8293                                         mono_array_setref (arr, i, item);
8294                                 }
8295                                 break;
8296                         default:
8297                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8298                 }
8299                 *end=p;
8300                 return arr;
8301         }
8302         default:
8303                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8304         }
8305         return NULL;
8306 }
8307
8308 static MonoObject*
8309 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8310 {
8311         static MonoClass *klass;
8312         static MonoMethod *ctor;
8313         MonoObject *retval;
8314         void *params [2], *unboxed;
8315
8316         if (!klass)
8317                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8318         if (!ctor)
8319                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8320         
8321         params [0] = mono_type_get_object (mono_domain_get (), t);
8322         params [1] = val;
8323         retval = mono_object_new (mono_domain_get (), klass);
8324         unboxed = mono_object_unbox (retval);
8325         mono_runtime_invoke (ctor, unboxed, params, NULL);
8326
8327         return retval;
8328 }
8329
8330 static MonoObject*
8331 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8332 {
8333         static MonoClass *klass;
8334         static MonoMethod *ctor;
8335         MonoObject *retval;
8336         void *unboxed, *params [2];
8337
8338         if (!klass)
8339                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8340         if (!ctor)
8341                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8342
8343         params [0] = minfo;
8344         params [1] = typedarg;
8345         retval = mono_object_new (mono_domain_get (), klass);
8346         unboxed = mono_object_unbox (retval);
8347         mono_runtime_invoke (ctor, unboxed, params, NULL);
8348
8349         return retval;
8350 }
8351
8352 static gboolean
8353 type_is_reference (MonoType *type)
8354 {
8355         switch (type->type) {
8356         case MONO_TYPE_BOOLEAN:
8357         case MONO_TYPE_CHAR:
8358         case MONO_TYPE_U:
8359         case MONO_TYPE_I:
8360         case MONO_TYPE_U1:
8361         case MONO_TYPE_I1:
8362         case MONO_TYPE_U2:
8363         case MONO_TYPE_I2:
8364         case MONO_TYPE_U4:
8365         case MONO_TYPE_I4:
8366         case MONO_TYPE_U8:
8367         case MONO_TYPE_I8:
8368         case MONO_TYPE_R8:
8369         case MONO_TYPE_R4:
8370         case MONO_TYPE_VALUETYPE:
8371                 return FALSE;
8372         default:
8373                 return TRUE;
8374         }
8375 }
8376
8377 static void
8378 free_param_data (MonoMethodSignature *sig, void **params) {
8379         int i;
8380         for (i = 0; i < sig->param_count; ++i) {
8381                 if (!type_is_reference (sig->params [i]))
8382                         g_free (params [i]);
8383         }
8384 }
8385
8386 /*
8387  * Find the field index in the metadata FieldDef table.
8388  */
8389 static guint32
8390 find_field_index (MonoClass *klass, MonoClassField *field) {
8391         int i;
8392
8393         for (i = 0; i < klass->field.count; ++i) {
8394                 if (field == &klass->fields [i])
8395                         return klass->field.first + 1 + i;
8396         }
8397         return 0;
8398 }
8399
8400 /*
8401  * Find the property index in the metadata Property table.
8402  */
8403 static guint32
8404 find_property_index (MonoClass *klass, MonoProperty *property) {
8405         int i;
8406
8407         for (i = 0; i < klass->ext->property.count; ++i) {
8408                 if (property == &klass->ext->properties [i])
8409                         return klass->ext->property.first + 1 + i;
8410         }
8411         return 0;
8412 }
8413
8414 /*
8415  * Find the event index in the metadata Event table.
8416  */
8417 static guint32
8418 find_event_index (MonoClass *klass, MonoEvent *event) {
8419         int i;
8420
8421         for (i = 0; i < klass->ext->event.count; ++i) {
8422                 if (event == &klass->ext->events [i])
8423                         return klass->ext->event.first + 1 + i;
8424         }
8425         return 0;
8426 }
8427
8428 static MonoObject*
8429 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8430 {
8431         const char *p = (const char*)data;
8432         const char *named;
8433         guint32 i, j, num_named;
8434         MonoObject *attr;
8435         void *params_buf [32];
8436         void **params = NULL;
8437         MonoMethodSignature *sig;
8438         MonoObject *exc = NULL;
8439
8440         mono_error_init (error);
8441
8442         mono_class_init (method->klass);
8443
8444         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8445                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8446                 return NULL;
8447         }
8448
8449         if (len == 0) {
8450                 attr = mono_object_new (mono_domain_get (), method->klass);
8451                 mono_runtime_invoke (method, attr, NULL, NULL);
8452                 return attr;
8453         }
8454
8455         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8456                 return NULL;
8457
8458         /*g_print ("got attr %s\n", method->klass->name);*/
8459
8460         sig = mono_method_signature (method);
8461         if (sig->param_count < 32) {
8462                 params = params_buf;
8463                 memset (params, 0, sizeof (void*) * sig->param_count);
8464         } else {
8465                 /* Allocate using GC so it gets GC tracking */
8466                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8467         }
8468
8469         /* skip prolog */
8470         p += 2;
8471         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8472                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8473                 if (!mono_error_ok (error))
8474                         goto fail;
8475         }
8476
8477         named = p;
8478         attr = mono_object_new (mono_domain_get (), method->klass);
8479
8480         mono_runtime_invoke (method, attr, params, &exc);
8481         if (exc)
8482                 goto fail;
8483         num_named = read16 (named);
8484         named += 2;
8485         for (j = 0; j < num_named; j++) {
8486                 gint name_len;
8487                 char *name, named_type, data_type;
8488                 named_type = *named++;
8489                 data_type = *named++; /* type of data */
8490                 if (data_type == MONO_TYPE_SZARRAY)
8491                         data_type = *named++;
8492                 if (data_type == MONO_TYPE_ENUM) {
8493                         gint type_len;
8494                         char *type_name;
8495                         type_len = mono_metadata_decode_blob_size (named, &named);
8496                         type_name = g_malloc (type_len + 1);
8497                         memcpy (type_name, named, type_len);
8498                         type_name [type_len] = 0;
8499                         named += type_len;
8500                         /* FIXME: lookup the type and check type consistency */
8501                         g_free (type_name);
8502                 }
8503                 name_len = mono_metadata_decode_blob_size (named, &named);
8504                 name = g_malloc (name_len + 1);
8505                 memcpy (name, named, name_len);
8506                 name [name_len] = 0;
8507                 named += name_len;
8508                 if (named_type == 0x53) {
8509                         MonoClassField *field;
8510                         void *val;
8511
8512                         /* how this fail is a blackbox */
8513                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8514                         if (!field) {
8515                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8516                                 g_free (name);
8517                                 goto fail;
8518                         }
8519
8520                         val = load_cattr_value (image, field->type, named, &named, error);
8521                         if (!mono_error_ok (error)) {
8522                                 g_free (name);
8523                                 if (!type_is_reference (field->type))
8524                                         g_free (val);
8525                                 goto fail;
8526                         }
8527
8528                         mono_field_set_value (attr, field, val);
8529                         if (!type_is_reference (field->type))
8530                                 g_free (val);
8531                 } else if (named_type == 0x54) {
8532                         MonoProperty *prop;
8533                         void *pparams [1];
8534                         MonoType *prop_type;
8535
8536                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8537
8538                         if (!prop) {
8539                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8540                                 g_free (name);
8541                                 goto fail;
8542                         }
8543
8544                         if (!prop->set) {
8545                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8546                                 g_free (name);
8547                                 goto fail;
8548                         }
8549
8550                         /* can we have more that 1 arg in a custom attr named property? */
8551                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8552                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8553
8554                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8555                         if (!mono_error_ok (error)) {
8556                                 g_free (name);
8557                                 if (!type_is_reference (prop_type))
8558                                         g_free (pparams [0]);
8559                                 goto fail;
8560                         }
8561
8562
8563                         mono_property_set_value (prop, attr, pparams, NULL);
8564                         if (!type_is_reference (prop_type))
8565                                 g_free (pparams [0]);
8566                 }
8567                 g_free (name);
8568         }
8569
8570         free_param_data (method->signature, params);
8571         if (params != params_buf)
8572                 mono_gc_free_fixed (params);
8573
8574         return attr;
8575
8576 fail:
8577         free_param_data (method->signature, params);
8578         if (params != params_buf)
8579                 mono_gc_free_fixed (params);
8580         if (exc)
8581                 mono_raise_exception ((MonoException*)exc);
8582         return NULL;
8583 }
8584         
8585 /*
8586  * mono_reflection_create_custom_attr_data_args:
8587  *
8588  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8589  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8590  * NAMED_ARG_INFO will contain information about the named arguments.
8591  */
8592 void
8593 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)
8594 {
8595         MonoArray *typedargs, *namedargs;
8596         MonoClass *attrklass;
8597         MonoDomain *domain;
8598         const char *p = (const char*)data;
8599         const char *named;
8600         guint32 i, j, num_named;
8601         CattrNamedArg *arginfo = NULL;
8602
8603         *typed_args = NULL;
8604         *named_args = NULL;
8605         *named_arg_info = NULL;
8606
8607         mono_error_init (error);
8608
8609         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8610                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8611                 return;
8612         }
8613
8614         mono_class_init (method->klass);
8615         
8616         domain = mono_domain_get ();
8617
8618         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8619                 return;
8620
8621         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8622         
8623         /* skip prolog */
8624         p += 2;
8625         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8626                 MonoObject *obj;
8627                 void *val;
8628
8629                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8630                 if (!mono_error_ok (error)) {
8631                         if (!type_is_reference (mono_method_signature (method)->params [i]))
8632                                 g_free (val);
8633                         return;
8634                 }
8635
8636                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8637                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8638                 mono_array_setref (typedargs, i, obj);
8639
8640                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8641                         g_free (val);
8642         }
8643
8644         named = p;
8645         num_named = read16 (named);
8646         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8647         named += 2;
8648         attrklass = method->klass;
8649
8650         arginfo = g_new0 (CattrNamedArg, num_named);
8651         *named_arg_info = arginfo;
8652
8653         for (j = 0; j < num_named; j++) {
8654                 gint name_len;
8655                 char *name, named_type, data_type;
8656                 named_type = *named++;
8657                 data_type = *named++; /* type of data */
8658                 if (data_type == MONO_TYPE_SZARRAY)
8659                         data_type = *named++;
8660                 if (data_type == MONO_TYPE_ENUM) {
8661                         gint type_len;
8662                         char *type_name;
8663                         type_len = mono_metadata_decode_blob_size (named, &named);
8664                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8665                                 goto fail;
8666
8667                         type_name = g_malloc (type_len + 1);
8668                         memcpy (type_name, named, type_len);
8669                         type_name [type_len] = 0;
8670                         named += type_len;
8671                         /* FIXME: lookup the type and check type consistency */
8672                         g_free (type_name);
8673                 }
8674                 name_len = mono_metadata_decode_blob_size (named, &named);
8675                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8676                         goto fail;
8677                 name = g_malloc (name_len + 1);
8678                 memcpy (name, named, name_len);
8679                 name [name_len] = 0;
8680                 named += name_len;
8681                 if (named_type == 0x53) {
8682                         MonoObject *obj;
8683                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8684                         void *val;
8685
8686                         if (!field) {
8687                                 g_free (name);
8688                                 goto fail;
8689                         }
8690
8691                         arginfo [j].type = field->type;
8692                         arginfo [j].field = field;
8693
8694                         val = load_cattr_value (image, field->type, named, &named, error);
8695                         if (!mono_error_ok (error)) {
8696                                 if (!type_is_reference (field->type))
8697                                         g_free (val);
8698                                 g_free (name);
8699                                 return;
8700                         }
8701
8702                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8703                         mono_array_setref (namedargs, j, obj);
8704                         if (!type_is_reference (field->type))
8705                                 g_free (val);
8706                 } else if (named_type == 0x54) {
8707                         MonoObject *obj;
8708                         MonoType *prop_type;
8709                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8710                         void *val;
8711
8712                         if (!prop || !prop->set) {
8713                                 g_free (name);
8714                                 goto fail;
8715                         }
8716
8717                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8718                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8719
8720                         arginfo [j].type = prop_type;
8721                         arginfo [j].prop = prop;
8722
8723                         val = load_cattr_value (image, prop_type, named, &named, error);
8724                         if (!mono_error_ok (error)) {
8725                                 if (!type_is_reference (prop_type))
8726                                         g_free (val);
8727                                 g_free (name);
8728                                 return;
8729                         }
8730
8731                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8732                         mono_array_setref (namedargs, j, obj);
8733                         if (!type_is_reference (prop_type))
8734                                 g_free (val);
8735                 }
8736                 g_free (name);
8737         }
8738
8739         *typed_args = typedargs;
8740         *named_args = namedargs;
8741         return;
8742 fail:
8743         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8744         g_free (arginfo);
8745         *named_arg_info = NULL;
8746 }
8747
8748 void
8749 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8750 {
8751         MonoDomain *domain;
8752         MonoArray *typedargs, *namedargs;
8753         MonoImage *image;
8754         MonoMethod *method;
8755         CattrNamedArg *arginfo = NULL;
8756         MonoError error;
8757         int i;
8758
8759         *ctor_args = NULL;
8760         *named_args = NULL;
8761
8762         if (len == 0)
8763                 return;
8764
8765         image = assembly->assembly->image;
8766         method = ref_method->method;
8767         domain = mono_object_domain (ref_method);
8768
8769         if (!mono_class_init (method->klass))
8770                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8771
8772         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8773         if (!mono_error_ok (&error))
8774                 mono_error_raise_exception (&error);
8775         if (mono_loader_get_last_error ())
8776                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8777
8778         if (!typedargs || !namedargs) {
8779                 g_free (arginfo);
8780                 return;
8781         }
8782
8783         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8784                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8785                 MonoObject *typedarg;
8786
8787                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8788                 mono_array_setref (typedargs, i, typedarg);
8789         }
8790
8791         for (i = 0; i < mono_array_length (namedargs); ++i) {
8792                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8793                 MonoObject *typedarg, *namedarg, *minfo;
8794
8795                 if (arginfo [i].prop)
8796                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8797                 else
8798                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8799
8800                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8801                 namedarg = create_cattr_named_arg (minfo, typedarg);
8802
8803                 mono_array_setref (namedargs, i, namedarg);
8804         }
8805
8806         *ctor_args = typedargs;
8807         *named_args = namedargs;
8808         g_free (arginfo);
8809 }
8810
8811 static MonoObject*
8812 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8813 {
8814         static MonoMethod *ctor;
8815         MonoDomain *domain;
8816         MonoObject *attr;
8817         void *params [4];
8818
8819         g_assert (image->assembly);
8820
8821         if (!ctor)
8822                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8823
8824         domain = mono_domain_get ();
8825         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8826         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8827         params [1] = mono_assembly_get_object (domain, image->assembly);
8828         params [2] = (gpointer)&cattr->data;
8829         params [3] = &cattr->data_size;
8830         mono_runtime_invoke (ctor, attr, params, NULL);
8831         return attr;
8832 }
8833
8834 static MonoArray*
8835 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8836 {
8837         MonoArray *result;
8838         MonoObject *attr;
8839         int i, n;
8840
8841         mono_error_init (error);
8842
8843         n = 0;
8844         for (i = 0; i < cinfo->num_attrs; ++i) {
8845                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8846                         n ++;
8847         }
8848
8849         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8850         n = 0;
8851         for (i = 0; i < cinfo->num_attrs; ++i) {
8852                 if (!cinfo->attrs [i].ctor)
8853                         /* The cattr type is not finished yet */
8854                         /* We should include the type name but cinfo doesn't contain it */
8855                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8856                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8857                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8858                         if (!mono_error_ok (error))
8859                                 return result;
8860                         mono_array_setref (result, n, attr);
8861                         n ++;
8862                 }
8863         }
8864         return result;
8865 }
8866
8867 MonoArray*
8868 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8869 {
8870         MonoError error;
8871         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8872         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8873
8874         return result;
8875 }
8876
8877 static MonoArray*
8878 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8879 {
8880         MonoArray *result;
8881         MonoObject *attr;
8882         int i;
8883         
8884         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8885         for (i = 0; i < cinfo->num_attrs; ++i) {
8886                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8887                 mono_array_setref (result, i, attr);
8888         }
8889         return result;
8890 }
8891
8892 /**
8893  * mono_custom_attrs_from_index:
8894  *
8895  * Returns: NULL if no attributes are found or if a loading error occurs.
8896  */
8897 MonoCustomAttrInfo*
8898 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8899 {
8900         guint32 mtoken, i, len;
8901         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8902         MonoTableInfo *ca;
8903         MonoCustomAttrInfo *ainfo;
8904         GList *tmp, *list = NULL;
8905         const char *data;
8906         MonoCustomAttrEntry* attr;
8907
8908         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8909
8910         i = mono_metadata_custom_attrs_from_index (image, idx);
8911         if (!i)
8912                 return NULL;
8913         i --;
8914         while (i < ca->rows) {
8915                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8916                         break;
8917                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8918                 ++i;
8919         }
8920         len = g_list_length (list);
8921         if (!len)
8922                 return NULL;
8923         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8924         ainfo->num_attrs = len;
8925         ainfo->image = image;
8926         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
8927                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8928                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8929                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8930                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8931                         mtoken |= MONO_TOKEN_METHOD_DEF;
8932                         break;
8933                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8934                         mtoken |= MONO_TOKEN_MEMBER_REF;
8935                         break;
8936                 default:
8937                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8938                         break;
8939                 }
8940                 attr = &ainfo->attrs [i - 1];
8941                 attr->ctor = mono_get_method (image, mtoken, NULL);
8942                 if (!attr->ctor) {
8943                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8944                         g_list_free (list);
8945                         g_free (ainfo);
8946                         return NULL;
8947                 }
8948
8949                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8950                         /*FIXME raising an exception here doesn't make any sense*/
8951                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8952                         g_list_free (list);
8953                         g_free (ainfo);
8954                         return NULL;
8955                 }
8956                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8957                 attr->data_size = mono_metadata_decode_value (data, &data);
8958                 attr->data = (guchar*)data;
8959         }
8960         g_list_free (list);
8961
8962         return ainfo;
8963 }
8964
8965 MonoCustomAttrInfo*
8966 mono_custom_attrs_from_method (MonoMethod *method)
8967 {
8968         guint32 idx;
8969
8970         /*
8971          * An instantiated method has the same cattrs as the generic method definition.
8972          *
8973          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8974          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8975          */
8976         if (method->is_inflated)
8977                 method = ((MonoMethodInflated *) method)->declaring;
8978         
8979         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
8980                 return lookup_custom_attr (method->klass->image, method);
8981
8982         if (!method->token)
8983                 /* Synthetic methods */
8984                 return NULL;
8985
8986         idx = mono_method_get_index (method);
8987         idx <<= MONO_CUSTOM_ATTR_BITS;
8988         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8989         return mono_custom_attrs_from_index (method->klass->image, idx);
8990 }
8991
8992 MonoCustomAttrInfo*
8993 mono_custom_attrs_from_class (MonoClass *klass)
8994 {
8995         guint32 idx;
8996
8997         if (klass->generic_class)
8998                 klass = klass->generic_class->container_class;
8999
9000         if (image_is_dynamic (klass->image))
9001                 return lookup_custom_attr (klass->image, klass);
9002
9003         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9004                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9005                 idx <<= MONO_CUSTOM_ATTR_BITS;
9006                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9007         } else {
9008                 idx = mono_metadata_token_index (klass->type_token);
9009                 idx <<= MONO_CUSTOM_ATTR_BITS;
9010                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9011         }
9012         return mono_custom_attrs_from_index (klass->image, idx);
9013 }
9014
9015 MonoCustomAttrInfo*
9016 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9017 {
9018         guint32 idx;
9019         
9020         if (image_is_dynamic (assembly->image))
9021                 return lookup_custom_attr (assembly->image, assembly);
9022         idx = 1; /* there is only one assembly */
9023         idx <<= MONO_CUSTOM_ATTR_BITS;
9024         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9025         return mono_custom_attrs_from_index (assembly->image, idx);
9026 }
9027
9028 static MonoCustomAttrInfo*
9029 mono_custom_attrs_from_module (MonoImage *image)
9030 {
9031         guint32 idx;
9032         
9033         if (image_is_dynamic (image))
9034                 return lookup_custom_attr (image, image);
9035         idx = 1; /* there is only one module */
9036         idx <<= MONO_CUSTOM_ATTR_BITS;
9037         idx |= MONO_CUSTOM_ATTR_MODULE;
9038         return mono_custom_attrs_from_index (image, idx);
9039 }
9040
9041 MonoCustomAttrInfo*
9042 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9043 {
9044         guint32 idx;
9045         
9046         if (image_is_dynamic (klass->image)) {
9047                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9048                 return lookup_custom_attr (klass->image, property);
9049         }
9050         idx = find_property_index (klass, property);
9051         idx <<= MONO_CUSTOM_ATTR_BITS;
9052         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9053         return mono_custom_attrs_from_index (klass->image, idx);
9054 }
9055
9056 MonoCustomAttrInfo*
9057 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9058 {
9059         guint32 idx;
9060         
9061         if (image_is_dynamic (klass->image)) {
9062                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9063                 return lookup_custom_attr (klass->image, event);
9064         }
9065         idx = find_event_index (klass, event);
9066         idx <<= MONO_CUSTOM_ATTR_BITS;
9067         idx |= MONO_CUSTOM_ATTR_EVENT;
9068         return mono_custom_attrs_from_index (klass->image, idx);
9069 }
9070
9071 MonoCustomAttrInfo*
9072 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9073 {
9074         guint32 idx;
9075         if (image_is_dynamic (klass->image)) {
9076                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9077                 return lookup_custom_attr (klass->image, field);
9078         }
9079         idx = find_field_index (klass, field);
9080         idx <<= MONO_CUSTOM_ATTR_BITS;
9081         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9082         return mono_custom_attrs_from_index (klass->image, idx);
9083 }
9084
9085 /**
9086  * mono_custom_attrs_from_param:
9087  * @method: handle to the method that we want to retrieve custom parameter information from
9088  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9089  *
9090  * The result must be released with mono_custom_attrs_free().
9091  *
9092  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9093  */
9094 MonoCustomAttrInfo*
9095 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9096 {
9097         MonoTableInfo *ca;
9098         guint32 i, idx, method_index;
9099         guint32 param_list, param_last, param_pos, found;
9100         MonoImage *image;
9101         MonoReflectionMethodAux *aux;
9102
9103         /*
9104          * An instantiated method has the same cattrs as the generic method definition.
9105          *
9106          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9107          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9108          */
9109         if (method->is_inflated)
9110                 method = ((MonoMethodInflated *) method)->declaring;
9111
9112         if (image_is_dynamic (method->klass->image)) {
9113                 MonoCustomAttrInfo *res, *ainfo;
9114                 int size;
9115
9116                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9117                 if (!aux || !aux->param_cattr)
9118                         return NULL;
9119
9120                 /* Need to copy since it will be freed later */
9121                 ainfo = aux->param_cattr [param];
9122                 if (!ainfo)
9123                         return NULL;
9124                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9125                 res = g_malloc0 (size);
9126                 memcpy (res, ainfo, size);
9127                 return res;
9128         }
9129
9130         image = method->klass->image;
9131         method_index = mono_method_get_index (method);
9132         if (!method_index)
9133                 return NULL;
9134         ca = &image->tables [MONO_TABLE_METHOD];
9135
9136         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9137         if (method_index == ca->rows) {
9138                 ca = &image->tables [MONO_TABLE_PARAM];
9139                 param_last = ca->rows + 1;
9140         } else {
9141                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9142                 ca = &image->tables [MONO_TABLE_PARAM];
9143         }
9144         found = FALSE;
9145         for (i = param_list; i < param_last; ++i) {
9146                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9147                 if (param_pos == param) {
9148                         found = TRUE;
9149                         break;
9150                 }
9151         }
9152         if (!found)
9153                 return NULL;
9154         idx = i;
9155         idx <<= MONO_CUSTOM_ATTR_BITS;
9156         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9157         return mono_custom_attrs_from_index (image, idx);
9158 }
9159
9160 gboolean
9161 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9162 {
9163         int i;
9164         MonoClass *klass;
9165         for (i = 0; i < ainfo->num_attrs; ++i) {
9166                 klass = ainfo->attrs [i].ctor->klass;
9167                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9168                         return TRUE;
9169         }
9170         return FALSE;
9171 }
9172
9173 MonoObject*
9174 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9175 {
9176         MonoError error;
9177         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9178         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9179         return res;
9180 }
9181
9182 MonoObject*
9183 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9184 {
9185         int i, attr_index;
9186         MonoClass *klass;
9187         MonoArray *attrs;
9188
9189         mono_error_init (error);
9190
9191         attr_index = -1;
9192         for (i = 0; i < ainfo->num_attrs; ++i) {
9193                 klass = ainfo->attrs [i].ctor->klass;
9194                 if (mono_class_has_parent (klass, attr_klass)) {
9195                         attr_index = i;
9196                         break;
9197                 }
9198         }
9199         if (attr_index == -1)
9200                 return NULL;
9201
9202         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9203         if (!mono_error_ok (error))
9204                 return NULL;
9205         return mono_array_get (attrs, MonoObject*, attr_index);
9206 }
9207
9208 /*
9209  * mono_reflection_get_custom_attrs_info:
9210  * @obj: a reflection object handle
9211  *
9212  * Return the custom attribute info for attributes defined for the
9213  * reflection handle @obj. The objects.
9214  *
9215  * FIXME this function leaks like a sieve for SRE objects.
9216  */
9217 MonoCustomAttrInfo*
9218 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9219 {
9220         MonoClass *klass;
9221         MonoCustomAttrInfo *cinfo = NULL;
9222         
9223         klass = obj->vtable->klass;
9224         if (klass == mono_defaults.monotype_class) {
9225                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9226                 klass = mono_class_from_mono_type (type);
9227                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9228                 cinfo = mono_custom_attrs_from_class (klass);
9229         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9230                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9231                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9232         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9233                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9234                 cinfo = mono_custom_attrs_from_module (module->image);
9235         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9236                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9237                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9238         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9239                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9240                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9241         } else if (strcmp ("MonoField", klass->name) == 0) {
9242                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9243                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9244         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9245                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9246                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9247         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9248                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9249                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9250         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9251                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9252                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9253                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9254                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9255                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9256                 } else if (is_sr_mono_property (member_class)) {
9257                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9258                         MonoMethod *method;
9259                         if (!(method = prop->property->get))
9260                                 method = prop->property->set;
9261                         g_assert (method);
9262
9263                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9264                 } 
9265 #ifndef DISABLE_REFLECTION_EMIT
9266                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9267                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9268                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9269                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9270                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9271                         MonoMethod *method = NULL;
9272                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9273                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9274                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9275                                 method = ((MonoReflectionMethod *)c->cb)->method;
9276                         else
9277                                 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));
9278
9279                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9280                 } 
9281 #endif
9282                 else {
9283                         char *type_name = mono_type_get_full_name (member_class);
9284                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9285                         MonoException *ex = mono_get_exception_not_supported  (msg);
9286                         g_free (type_name);
9287                         g_free (msg);
9288                         mono_raise_exception (ex);
9289                 }
9290         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9291                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9292                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9293         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9294                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9295                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9296         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9297                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9298                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9299         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9300                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9301                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9302         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9303                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9304                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9305         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9306                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9307                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9308         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9309                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9310                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9311         } else { /* handle other types here... */
9312                 g_error ("get custom attrs not yet supported for %s", klass->name);
9313         }
9314
9315         return cinfo;
9316 }
9317
9318 /*
9319  * mono_reflection_get_custom_attrs_by_type:
9320  * @obj: a reflection object handle
9321  *
9322  * Return an array with all the custom attributes defined of the
9323  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9324  * of that type are returned. The objects are fully build. Return NULL if a loading error
9325  * occurs.
9326  */
9327 MonoArray*
9328 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9329 {
9330         MonoArray *result;
9331         MonoCustomAttrInfo *cinfo;
9332
9333         mono_error_init (error);
9334
9335         cinfo = mono_reflection_get_custom_attrs_info (obj);
9336         if (cinfo) {
9337                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9338                 if (!cinfo->cached)
9339                         mono_custom_attrs_free (cinfo);
9340         } else {
9341                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9342                 if (mono_loader_get_last_error ())
9343                         return NULL;
9344                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9345         }
9346
9347         return result;
9348 }
9349
9350 /*
9351  * mono_reflection_get_custom_attrs:
9352  * @obj: a reflection object handle
9353  *
9354  * Return an array with all the custom attributes defined of the
9355  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9356  * occurs.
9357  */
9358 MonoArray*
9359 mono_reflection_get_custom_attrs (MonoObject *obj)
9360 {
9361         MonoError error;
9362
9363         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9364 }
9365
9366 /*
9367  * mono_reflection_get_custom_attrs_data:
9368  * @obj: a reflection obj handle
9369  *
9370  * Returns an array of System.Reflection.CustomAttributeData,
9371  * which include information about attributes reflected on
9372  * types loaded using the Reflection Only methods
9373  */
9374 MonoArray*
9375 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9376 {
9377         MonoArray *result;
9378         MonoCustomAttrInfo *cinfo;
9379
9380         cinfo = mono_reflection_get_custom_attrs_info (obj);
9381         if (cinfo) {
9382                 result = mono_custom_attrs_data_construct (cinfo);
9383                 if (!cinfo->cached)
9384                         mono_custom_attrs_free (cinfo);
9385         } else
9386                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9387
9388         return result;
9389 }
9390
9391 static MonoReflectionType*
9392 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9393 {
9394         static MonoMethod *method_get_underlying_system_type = NULL;
9395         MonoMethod *usertype_method;
9396
9397         if (!method_get_underlying_system_type)
9398                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9399         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9400         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9401 }
9402
9403
9404 static gboolean
9405 is_corlib_type (MonoClass *class)
9406 {
9407         return class->image == mono_defaults.corlib;
9408 }
9409
9410 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9411         static MonoClass *cached_class; \
9412         if (cached_class) \
9413                 return cached_class == _class; \
9414         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9415                 cached_class = _class; \
9416                 return TRUE; \
9417         } \
9418         return FALSE; \
9419 } while (0) \
9420
9421
9422 #ifndef DISABLE_REFLECTION_EMIT
9423 static gboolean
9424 is_sre_array (MonoClass *class)
9425 {
9426         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9427 }
9428
9429 static gboolean
9430 is_sre_byref (MonoClass *class)
9431 {
9432         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9433 }
9434
9435 static gboolean
9436 is_sre_pointer (MonoClass *class)
9437 {
9438         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9439 }
9440
9441 static gboolean
9442 is_sre_generic_instance (MonoClass *class)
9443 {
9444         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9445 }
9446
9447 static gboolean
9448 is_sre_type_builder (MonoClass *class)
9449 {
9450         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9451 }
9452
9453 static gboolean
9454 is_sre_method_builder (MonoClass *class)
9455 {
9456         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9457 }
9458
9459 static gboolean
9460 is_sre_ctor_builder (MonoClass *class)
9461 {
9462         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9463 }
9464
9465 static gboolean
9466 is_sre_field_builder (MonoClass *class)
9467 {
9468         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9469 }
9470
9471 static gboolean
9472 is_sre_method_on_tb_inst (MonoClass *class)
9473 {
9474         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9475 }
9476
9477 static gboolean
9478 is_sre_ctor_on_tb_inst (MonoClass *class)
9479 {
9480         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9481 }
9482
9483 MonoType*
9484 mono_reflection_type_get_handle (MonoReflectionType* ref)
9485 {
9486         MonoClass *class;
9487         if (!ref)
9488                 return NULL;
9489         if (ref->type)
9490                 return ref->type;
9491
9492         if (is_usertype (ref)) {
9493                 ref = mono_reflection_type_get_underlying_system_type (ref);
9494                 if (ref == NULL || is_usertype (ref))
9495                         return NULL;
9496                 if (ref->type)
9497                         return ref->type;
9498         }
9499
9500         class = mono_object_class (ref);
9501
9502         if (is_sre_array (class)) {
9503                 MonoType *res;
9504                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9505                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9506                 g_assert (base);
9507                 if (sre_array->rank == 0) //single dimentional array
9508                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9509                 else
9510                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9511                 sre_array->type.type = res;
9512                 return res;
9513         } else if (is_sre_byref (class)) {
9514                 MonoType *res;
9515                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9516                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9517                 g_assert (base);
9518                 res = &mono_class_from_mono_type (base)->this_arg;
9519                 sre_byref->type.type = res;
9520                 return res;
9521         } else if (is_sre_pointer (class)) {
9522                 MonoType *res;
9523                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9524                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9525                 g_assert (base);
9526                 res = &mono_ptr_class_get (base)->byval_arg;
9527                 sre_pointer->type.type = res;
9528                 return res;
9529         } else if (is_sre_generic_instance (class)) {
9530                 MonoType *res, **types;
9531                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9532                 int i, count;
9533
9534                 count = mono_array_length (gclass->type_arguments);
9535                 types = g_new0 (MonoType*, count);
9536                 for (i = 0; i < count; ++i) {
9537                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9538                         types [i] = mono_reflection_type_get_handle (t);
9539                         if (!types[i]) {
9540                                 g_free (types);
9541                                 return NULL;
9542                         }
9543                 }
9544
9545                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9546                 g_free (types);
9547                 g_assert (res);
9548                 gclass->type.type = res;
9549                 return res;
9550         }
9551
9552         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9553         return NULL;
9554 }
9555
9556
9557
9558 void
9559 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9560 {
9561         mono_reflection_type_get_handle (type);
9562 }
9563
9564 void
9565 mono_reflection_register_with_runtime (MonoReflectionType *type)
9566 {
9567         MonoType *res = mono_reflection_type_get_handle (type);
9568         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9569         MonoClass *class;
9570
9571         if (!res)
9572                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9573
9574         class = mono_class_from_mono_type (res);
9575
9576         mono_loader_lock (); /*same locking as mono_type_get_object*/
9577         mono_domain_lock (domain);
9578
9579         if (!image_is_dynamic (class->image)) {
9580                 mono_class_setup_supertypes (class);
9581         } else {
9582                 if (!domain->type_hash)
9583                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9584                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9585                 mono_g_hash_table_insert (domain->type_hash, res, type);
9586         }
9587         mono_domain_unlock (domain);
9588         mono_loader_unlock ();
9589 }
9590
9591 /**
9592  * LOCKING: Assumes the loader lock is held.
9593  */
9594 static MonoMethodSignature*
9595 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9596         MonoMethodSignature *sig;
9597         int count, i;
9598
9599         count = parameters? mono_array_length (parameters): 0;
9600
9601         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9602         sig->param_count = count;
9603         sig->sentinelpos = -1; /* FIXME */
9604         for (i = 0; i < count; ++i)
9605                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9606         return sig;
9607 }
9608
9609 /**
9610  * LOCKING: Assumes the loader lock is held.
9611  */
9612 static MonoMethodSignature*
9613 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9614         MonoMethodSignature *sig;
9615
9616         sig = parameters_to_signature (image, ctor->parameters);
9617         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9618         sig->ret = &mono_defaults.void_class->byval_arg;
9619         return sig;
9620 }
9621
9622 /**
9623  * LOCKING: Assumes the loader lock is held.
9624  */
9625 static MonoMethodSignature*
9626 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9627         MonoMethodSignature *sig;
9628
9629         sig = parameters_to_signature (image, method->parameters);
9630         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9631         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9632         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9633         return sig;
9634 }
9635
9636 static MonoMethodSignature*
9637 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9638         MonoMethodSignature *sig;
9639
9640         sig = parameters_to_signature (NULL, method->parameters);
9641         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9642         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9643         sig->generic_param_count = 0;
9644         return sig;
9645 }
9646
9647 static void
9648 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9649 {
9650         MonoClass *klass = mono_object_class (prop);
9651         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9652                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9653                 *name = mono_string_to_utf8 (pb->name);
9654                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9655         } else {
9656                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9657                 *name = g_strdup (p->property->name);
9658                 if (p->property->get)
9659                         *type = mono_method_signature (p->property->get)->ret;
9660                 else
9661                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9662         }
9663 }
9664
9665 static void
9666 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9667 {
9668         MonoClass *klass = mono_object_class (field);
9669         if (strcmp (klass->name, "FieldBuilder") == 0) {
9670                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9671                 *name = mono_string_to_utf8 (fb->name);
9672                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9673         } else {
9674                 MonoReflectionField *f = (MonoReflectionField *)field;
9675                 *name = g_strdup (mono_field_get_name (f->field));
9676                 *type = f->field->type;
9677         }
9678 }
9679
9680 #else /* DISABLE_REFLECTION_EMIT */
9681
9682 void
9683 mono_reflection_register_with_runtime (MonoReflectionType *type)
9684 {
9685         /* This is empty */
9686 }
9687
9688 static gboolean
9689 is_sre_type_builder (MonoClass *class)
9690 {
9691         return FALSE;
9692 }
9693
9694 static gboolean
9695 is_sre_generic_instance (MonoClass *class)
9696 {
9697         return FALSE;
9698 }
9699
9700 static void
9701 init_type_builder_generics (MonoObject *type)
9702 {
9703 }
9704
9705 #endif /* !DISABLE_REFLECTION_EMIT */
9706
9707
9708 static gboolean
9709 is_sr_mono_field (MonoClass *class)
9710 {
9711         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9712 }
9713
9714 static gboolean
9715 is_sr_mono_property (MonoClass *class)
9716 {
9717         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9718 }
9719
9720 static gboolean
9721 is_sr_mono_method (MonoClass *class)
9722 {
9723         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9724 }
9725
9726 static gboolean
9727 is_sr_mono_cmethod (MonoClass *class)
9728 {
9729         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9730 }
9731
9732 static gboolean
9733 is_sr_mono_generic_method (MonoClass *class)
9734 {
9735         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9736 }
9737
9738 static gboolean
9739 is_sr_mono_generic_cmethod (MonoClass *class)
9740 {
9741         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9742 }
9743
9744 gboolean
9745 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9746 {
9747         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9748 }
9749
9750 static gboolean
9751 is_usertype (MonoReflectionType *ref)
9752 {
9753         MonoClass *class = mono_object_class (ref);
9754         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9755 }
9756
9757 static MonoReflectionType*
9758 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9759 {
9760         if (!type || type->type)
9761                 return type;
9762
9763         if (is_usertype (type)) {
9764                 type = mono_reflection_type_get_underlying_system_type (type);
9765                 if (is_usertype (type))
9766                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9767         }
9768
9769         return type;
9770 }
9771 /*
9772  * Encode a value in a custom attribute stream of bytes.
9773  * The value to encode is either supplied as an object in argument val
9774  * (valuetypes are boxed), or as a pointer to the data in the
9775  * argument argval.
9776  * @type represents the type of the value
9777  * @buffer is the start of the buffer
9778  * @p the current position in the buffer
9779  * @buflen contains the size of the buffer and is used to return the new buffer size
9780  * if this needs to be realloced.
9781  * @retbuffer and @retp return the start and the position of the buffer
9782  */
9783 static void
9784 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9785 {
9786         MonoTypeEnum simple_type;
9787         
9788         if ((p-buffer) + 10 >= *buflen) {
9789                 char *newbuf;
9790                 *buflen *= 2;
9791                 newbuf = g_realloc (buffer, *buflen);
9792                 p = newbuf + (p-buffer);
9793                 buffer = newbuf;
9794         }
9795         if (!argval)
9796                 argval = ((char*)arg + sizeof (MonoObject));
9797         simple_type = type->type;
9798 handle_enum:
9799         switch (simple_type) {
9800         case MONO_TYPE_BOOLEAN:
9801         case MONO_TYPE_U1:
9802         case MONO_TYPE_I1:
9803                 *p++ = *argval;
9804                 break;
9805         case MONO_TYPE_CHAR:
9806         case MONO_TYPE_U2:
9807         case MONO_TYPE_I2:
9808                 swap_with_size (p, argval, 2, 1);
9809                 p += 2;
9810                 break;
9811         case MONO_TYPE_U4:
9812         case MONO_TYPE_I4:
9813         case MONO_TYPE_R4:
9814                 swap_with_size (p, argval, 4, 1);
9815                 p += 4;
9816                 break;
9817         case MONO_TYPE_R8:
9818                 swap_with_size (p, argval, 8, 1);
9819                 p += 8;
9820                 break;
9821         case MONO_TYPE_U8:
9822         case MONO_TYPE_I8:
9823                 swap_with_size (p, argval, 8, 1);
9824                 p += 8;
9825                 break;
9826         case MONO_TYPE_VALUETYPE:
9827                 if (type->data.klass->enumtype) {
9828                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9829                         goto handle_enum;
9830                 } else {
9831                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9832                 }
9833                 break;
9834         case MONO_TYPE_STRING: {
9835                 char *str;
9836                 guint32 slen;
9837                 if (!arg) {
9838                         *p++ = 0xFF;
9839                         break;
9840                 }
9841                 str = mono_string_to_utf8 ((MonoString*)arg);
9842                 slen = strlen (str);
9843                 if ((p-buffer) + 10 + slen >= *buflen) {
9844                         char *newbuf;
9845                         *buflen *= 2;
9846                         *buflen += slen;
9847                         newbuf = g_realloc (buffer, *buflen);
9848                         p = newbuf + (p-buffer);
9849                         buffer = newbuf;
9850                 }
9851                 mono_metadata_encode_value (slen, p, &p);
9852                 memcpy (p, str, slen);
9853                 p += slen;
9854                 g_free (str);
9855                 break;
9856         }
9857         case MONO_TYPE_CLASS: {
9858                 char *str;
9859                 guint32 slen;
9860                 if (!arg) {
9861                         *p++ = 0xFF;
9862                         break;
9863                 }
9864 handle_type:
9865                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9866                 slen = strlen (str);
9867                 if ((p-buffer) + 10 + slen >= *buflen) {
9868                         char *newbuf;
9869                         *buflen *= 2;
9870                         *buflen += slen;
9871                         newbuf = g_realloc (buffer, *buflen);
9872                         p = newbuf + (p-buffer);
9873                         buffer = newbuf;
9874                 }
9875                 mono_metadata_encode_value (slen, p, &p);
9876                 memcpy (p, str, slen);
9877                 p += slen;
9878                 g_free (str);
9879                 break;
9880         }
9881         case MONO_TYPE_SZARRAY: {
9882                 int len, i;
9883                 MonoClass *eclass, *arg_eclass;
9884
9885                 if (!arg) {
9886                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9887                         break;
9888                 }
9889                 len = mono_array_length ((MonoArray*)arg);
9890                 *p++ = len & 0xff;
9891                 *p++ = (len >> 8) & 0xff;
9892                 *p++ = (len >> 16) & 0xff;
9893                 *p++ = (len >> 24) & 0xff;
9894                 *retp = p;
9895                 *retbuffer = buffer;
9896                 eclass = type->data.klass;
9897                 arg_eclass = mono_object_class (arg)->element_class;
9898
9899                 if (!eclass) {
9900                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9901                         eclass = mono_defaults.object_class;
9902                 }
9903                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9904                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9905                         int elsize = mono_class_array_element_size (arg_eclass);
9906                         for (i = 0; i < len; ++i) {
9907                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9908                                 elptr += elsize;
9909                         }
9910                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9911                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9912                         int elsize = mono_class_array_element_size (eclass);
9913                         for (i = 0; i < len; ++i) {
9914                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9915                                 elptr += elsize;
9916                         }
9917                 } else {
9918                         for (i = 0; i < len; ++i) {
9919                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9920                         }
9921                 }
9922                 break;
9923         }
9924         case MONO_TYPE_OBJECT: {
9925                 MonoClass *klass;
9926                 char *str;
9927                 guint32 slen;
9928
9929                 /*
9930                  * The parameter type is 'object' but the type of the actual
9931                  * argument is not. So we have to add type information to the blob
9932                  * too. This is completely undocumented in the spec.
9933                  */
9934
9935                 if (arg == NULL) {
9936                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9937                         *p++ = 0xFF;
9938                         break;
9939                 }
9940                 
9941                 klass = mono_object_class (arg);
9942
9943                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9944                         *p++ = 0x50;
9945                         goto handle_type;
9946                 } else if (klass->enumtype) {
9947                         *p++ = 0x55;
9948                 } else if (klass == mono_defaults.string_class) {
9949                         simple_type = MONO_TYPE_STRING;
9950                         *p++ = 0x0E;
9951                         goto handle_enum;
9952                 } else if (klass->rank == 1) {
9953                         *p++ = 0x1D;
9954                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9955                                 /* See Partition II, Appendix B3 */
9956                                 *p++ = 0x51;
9957                         else
9958                                 *p++ = klass->element_class->byval_arg.type;
9959                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9960                         break;
9961                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9962                         *p++ = simple_type = klass->byval_arg.type;
9963                         goto handle_enum;
9964                 } else {
9965                         g_error ("unhandled type in custom attr");
9966                 }
9967                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9968                 slen = strlen (str);
9969                 if ((p-buffer) + 10 + slen >= *buflen) {
9970                         char *newbuf;
9971                         *buflen *= 2;
9972                         *buflen += slen;
9973                         newbuf = g_realloc (buffer, *buflen);
9974                         p = newbuf + (p-buffer);
9975                         buffer = newbuf;
9976                 }
9977                 mono_metadata_encode_value (slen, p, &p);
9978                 memcpy (p, str, slen);
9979                 p += slen;
9980                 g_free (str);
9981                 simple_type = mono_class_enum_basetype (klass)->type;
9982                 goto handle_enum;
9983         }
9984         default:
9985                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9986         }
9987         *retp = p;
9988         *retbuffer = buffer;
9989 }
9990
9991 static void
9992 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9993 {
9994         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9995                 char *str = type_get_qualified_name (type, NULL);
9996                 int slen = strlen (str);
9997
9998                 *p++ = 0x55;
9999                 /*
10000                  * This seems to be optional...
10001                  * *p++ = 0x80;
10002                  */
10003                 mono_metadata_encode_value (slen, p, &p);
10004                 memcpy (p, str, slen);
10005                 p += slen;
10006                 g_free (str);
10007         } else if (type->type == MONO_TYPE_OBJECT) {
10008                 *p++ = 0x51;
10009         } else if (type->type == MONO_TYPE_CLASS) {
10010                 /* it should be a type: encode_cattr_value () has the check */
10011                 *p++ = 0x50;
10012         } else {
10013                 mono_metadata_encode_value (type->type, p, &p);
10014                 if (type->type == MONO_TYPE_SZARRAY)
10015                         /* See the examples in Partition VI, Annex B */
10016                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10017         }
10018
10019         *retp = p;
10020 }
10021
10022 #ifndef DISABLE_REFLECTION_EMIT
10023 static void
10024 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10025 {
10026         int len;
10027         /* Preallocate a large enough buffer */
10028         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10029                 char *str = type_get_qualified_name (type, NULL);
10030                 len = strlen (str);
10031                 g_free (str);
10032         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10033                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10034                 len = strlen (str);
10035                 g_free (str);
10036         } else {
10037                 len = 0;
10038         }
10039         len += strlen (name);
10040
10041         if ((p-buffer) + 20 + len >= *buflen) {
10042                 char *newbuf;
10043                 *buflen *= 2;
10044                 *buflen += len;
10045                 newbuf = g_realloc (buffer, *buflen);
10046                 p = newbuf + (p-buffer);
10047                 buffer = newbuf;
10048         }
10049
10050         encode_field_or_prop_type (type, p, &p);
10051
10052         len = strlen (name);
10053         mono_metadata_encode_value (len, p, &p);
10054         memcpy (p, name, len);
10055         p += len;
10056         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10057         *retp = p;
10058         *retbuffer = buffer;
10059 }
10060
10061 /*
10062  * mono_reflection_get_custom_attrs_blob:
10063  * @ctor: custom attribute constructor
10064  * @ctorArgs: arguments o the constructor
10065  * @properties:
10066  * @propValues:
10067  * @fields:
10068  * @fieldValues:
10069  * 
10070  * Creates the blob of data that needs to be saved in the metadata and that represents
10071  * the custom attributed described by @ctor, @ctorArgs etc.
10072  * Returns: a Byte array representing the blob of data.
10073  */
10074 MonoArray*
10075 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10076 {
10077         MonoArray *result;
10078         MonoMethodSignature *sig;
10079         MonoObject *arg;
10080         char *buffer, *p;
10081         guint32 buflen, i;
10082
10083         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10084                 /* sig is freed later so allocate it in the heap */
10085                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10086         } else {
10087                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10088         }
10089
10090         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10091         buflen = 256;
10092         p = buffer = g_malloc (buflen);
10093         /* write the prolog */
10094         *p++ = 1;
10095         *p++ = 0;
10096         for (i = 0; i < sig->param_count; ++i) {
10097                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10098                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10099         }
10100         i = 0;
10101         if (properties)
10102                 i += mono_array_length (properties);
10103         if (fields)
10104                 i += mono_array_length (fields);
10105         *p++ = i & 0xff;
10106         *p++ = (i >> 8) & 0xff;
10107         if (properties) {
10108                 MonoObject *prop;
10109                 for (i = 0; i < mono_array_length (properties); ++i) {
10110                         MonoType *ptype;
10111                         char *pname;
10112
10113                         prop = mono_array_get (properties, gpointer, i);
10114                         get_prop_name_and_type (prop, &pname, &ptype);
10115                         *p++ = 0x54; /* PROPERTY signature */
10116                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10117                         g_free (pname);
10118                 }
10119         }
10120
10121         if (fields) {
10122                 MonoObject *field;
10123                 for (i = 0; i < mono_array_length (fields); ++i) {
10124                         MonoType *ftype;
10125                         char *fname;
10126
10127                         field = mono_array_get (fields, gpointer, i);
10128                         get_field_name_and_type (field, &fname, &ftype);
10129                         *p++ = 0x53; /* FIELD signature */
10130                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10131                         g_free (fname);
10132                 }
10133         }
10134
10135         g_assert (p - buffer <= buflen);
10136         buflen = p - buffer;
10137         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10138         p = mono_array_addr (result, char, 0);
10139         memcpy (p, buffer, buflen);
10140         g_free (buffer);
10141         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10142                 g_free (sig);
10143         return result;
10144 }
10145
10146 /*
10147  * mono_reflection_setup_internal_class:
10148  * @tb: a TypeBuilder object
10149  *
10150  * Creates a MonoClass that represents the TypeBuilder.
10151  * This is a trick that lets us simplify a lot of reflection code
10152  * (and will allow us to support Build and Run assemblies easier).
10153  */
10154 void
10155 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10156 {
10157         MonoError error;
10158         MonoClass *klass, *parent;
10159
10160         RESOLVE_TYPE (tb->parent);
10161
10162         mono_loader_lock ();
10163
10164         if (tb->parent) {
10165                 /* check so we can compile corlib correctly */
10166                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10167                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10168                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10169                 } else {
10170                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10171                 }
10172         } else {
10173                 parent = NULL;
10174         }
10175         
10176         /* the type has already being created: it means we just have to change the parent */
10177         if (tb->type.type) {
10178                 klass = mono_class_from_mono_type (tb->type.type);
10179                 klass->parent = NULL;
10180                 /* fool mono_class_setup_parent */
10181                 klass->supertypes = NULL;
10182                 mono_class_setup_parent (klass, parent);
10183                 mono_class_setup_mono_type (klass);
10184                 mono_loader_unlock ();
10185                 return;
10186         }
10187
10188         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10189
10190         klass->image = &tb->module->dynamic_image->image;
10191
10192         klass->inited = 1; /* we lie to the runtime */
10193         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10194         if (!mono_error_ok (&error))
10195                 goto failure;
10196         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10197         if (!mono_error_ok (&error))
10198                 goto failure;
10199         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10200         klass->flags = tb->attrs;
10201         
10202         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10203
10204         klass->element_class = klass;
10205
10206         if (mono_class_get_ref_info (klass) == NULL) {
10207
10208                 mono_class_set_ref_info (klass, tb);
10209
10210                 /* Put into cache so mono_class_get_checked () will find it.
10211                 Skip nested types as those should not be available on the global scope. */
10212                 if (!tb->nesting_type)
10213                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10214
10215                 /*
10216                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10217                 by performing a mono_class_get which does the full resolution.
10218
10219                 Working around this semantics would require us to write a lot of code for no clear advantage.
10220                 */
10221                 mono_image_append_class_to_reflection_info_set (klass);
10222         } else {
10223                 g_assert (mono_class_get_ref_info (klass) == tb);
10224         }
10225
10226         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10227
10228         if (parent != NULL) {
10229                 mono_class_setup_parent (klass, parent);
10230         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10231                 const char *old_n = klass->name;
10232                 /* trick to get relative numbering right when compiling corlib */
10233                 klass->name = "BuildingObject";
10234                 mono_class_setup_parent (klass, mono_defaults.object_class);
10235                 klass->name = old_n;
10236         }
10237
10238         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10239                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10240                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10241                 klass->instance_size = sizeof (MonoObject);
10242                 klass->size_inited = 1;
10243                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10244         }
10245
10246         mono_class_setup_mono_type (klass);
10247
10248         mono_class_setup_supertypes (klass);
10249
10250         /*
10251          * FIXME: handle interfaces.
10252          */
10253
10254         tb->type.type = &klass->byval_arg;
10255
10256         if (tb->nesting_type) {
10257                 g_assert (tb->nesting_type->type);
10258                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10259         }
10260
10261         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10262
10263         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10264         
10265         mono_loader_unlock ();
10266         return;
10267
10268 failure:
10269         mono_loader_unlock ();
10270         mono_error_raise_exception (&error);
10271 }
10272
10273 /*
10274  * mono_reflection_setup_generic_class:
10275  * @tb: a TypeBuilder object
10276  *
10277  * Setup the generic class before adding the first generic parameter.
10278  */
10279 void
10280 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10281 {
10282 }
10283
10284 /*
10285  * mono_reflection_create_generic_class:
10286  * @tb: a TypeBuilder object
10287  *
10288  * Creates the generic class after all generic parameters have been added.
10289  */
10290 void
10291 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10292 {
10293         MonoClass *klass;
10294         int count, i;
10295
10296         klass = mono_class_from_mono_type (tb->type.type);
10297
10298         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10299
10300         if (klass->generic_container || (count == 0))
10301                 return;
10302
10303         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10304
10305         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10306
10307         klass->generic_container->owner.klass = klass;
10308         klass->generic_container->type_argc = count;
10309         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10310
10311         klass->is_generic = 1;
10312
10313         for (i = 0; i < count; i++) {
10314                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10315                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10316                 klass->generic_container->type_params [i] = *param;
10317                 /*Make sure we are a diferent type instance */
10318                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10319                 klass->generic_container->type_params [i].info.pklass = NULL;
10320                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10321
10322                 g_assert (klass->generic_container->type_params [i].param.owner);
10323         }
10324
10325         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10326 }
10327
10328 /*
10329  * mono_reflection_create_internal_class:
10330  * @tb: a TypeBuilder object
10331  *
10332  * Actually create the MonoClass that is associated with the TypeBuilder.
10333  */
10334 void
10335 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10336 {
10337         MonoClass *klass;
10338
10339         klass = mono_class_from_mono_type (tb->type.type);
10340
10341         mono_loader_lock ();
10342         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10343                 MonoReflectionFieldBuilder *fb;
10344                 MonoClass *ec;
10345                 MonoType *enum_basetype;
10346
10347                 g_assert (tb->fields != NULL);
10348                 g_assert (mono_array_length (tb->fields) >= 1);
10349
10350                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10351
10352                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10353                         mono_loader_unlock ();
10354                         return;
10355                 }
10356
10357                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10358                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10359                 if (!klass->element_class)
10360                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10361
10362                 /*
10363                  * get the element_class from the current corlib.
10364                  */
10365                 ec = default_class_from_mono_type (enum_basetype);
10366                 klass->instance_size = ec->instance_size;
10367                 klass->size_inited = 1;
10368                 /* 
10369                  * this is almost safe to do with enums and it's needed to be able
10370                  * to create objects of the enum type (for use in SetConstant).
10371                  */
10372                 /* FIXME: Does this mean enums can't have method overrides ? */
10373                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10374         }
10375         mono_loader_unlock ();
10376 }
10377
10378 static MonoMarshalSpec*
10379 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10380                                                                 MonoReflectionMarshal *minfo)
10381 {
10382         MonoMarshalSpec *res;
10383
10384         res = image_g_new0 (image, MonoMarshalSpec, 1);
10385         res->native = minfo->type;
10386
10387         switch (minfo->type) {
10388         case MONO_NATIVE_LPARRAY:
10389                 res->data.array_data.elem_type = minfo->eltype;
10390                 if (minfo->has_size) {
10391                         res->data.array_data.param_num = minfo->param_num;
10392                         res->data.array_data.num_elem = minfo->count;
10393                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10394                 }
10395                 else {
10396                         res->data.array_data.param_num = -1;
10397                         res->data.array_data.num_elem = -1;
10398                         res->data.array_data.elem_mult = -1;
10399                 }
10400                 break;
10401
10402         case MONO_NATIVE_BYVALTSTR:
10403         case MONO_NATIVE_BYVALARRAY:
10404                 res->data.array_data.num_elem = minfo->count;
10405                 break;
10406
10407         case MONO_NATIVE_CUSTOM:
10408                 if (minfo->marshaltyperef)
10409                         res->data.custom_data.custom_name =
10410                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10411                 if (minfo->mcookie)
10412                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10413                 break;
10414
10415         default:
10416                 break;
10417         }
10418
10419         return res;
10420 }
10421 #endif /* !DISABLE_REFLECTION_EMIT */
10422
10423 MonoReflectionMarshalAsAttribute*
10424 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10425                                                                                    MonoMarshalSpec *spec)
10426 {
10427         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10428         MonoReflectionMarshalAsAttribute *minfo;
10429         MonoType *mtype;
10430
10431         if (!System_Reflection_Emit_MarshalAsAttribute) {
10432                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10433                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10434                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10435         }
10436
10437         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10438         minfo->utype = spec->native;
10439
10440         switch (minfo->utype) {
10441         case MONO_NATIVE_LPARRAY:
10442                 minfo->array_subtype = spec->data.array_data.elem_type;
10443                 minfo->size_const = spec->data.array_data.num_elem;
10444                 if (spec->data.array_data.param_num != -1)
10445                         minfo->size_param_index = spec->data.array_data.param_num;
10446                 break;
10447
10448         case MONO_NATIVE_BYVALTSTR:
10449         case MONO_NATIVE_BYVALARRAY:
10450                 minfo->size_const = spec->data.array_data.num_elem;
10451                 break;
10452
10453         case MONO_NATIVE_CUSTOM:
10454                 if (spec->data.custom_data.custom_name) {
10455                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10456                         if (mtype)
10457                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10458
10459                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10460                 }
10461                 if (spec->data.custom_data.cookie)
10462                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10463                 break;
10464
10465         default:
10466                 break;
10467         }
10468
10469         return minfo;
10470 }
10471
10472 #ifndef DISABLE_REFLECTION_EMIT
10473 static MonoMethod*
10474 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10475                                          ReflectionMethodBuilder *rmb,
10476                                          MonoMethodSignature *sig)
10477 {
10478         MonoError error;
10479         MonoMethod *m;
10480         MonoMethodWrapper *wrapperm;
10481         MonoMarshalSpec **specs;
10482         MonoReflectionMethodAux *method_aux;
10483         MonoImage *image;
10484         gboolean dynamic;
10485         int i;
10486
10487         mono_error_init (&error);
10488         /*
10489          * Methods created using a MethodBuilder should have their memory allocated
10490          * inside the image mempool, while dynamic methods should have their memory
10491          * malloc'd.
10492          */
10493         dynamic = rmb->refs != NULL;
10494         image = dynamic ? NULL : klass->image;
10495
10496         if (!dynamic)
10497                 g_assert (!klass->generic_class);
10498
10499         mono_loader_lock ();
10500
10501         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10502                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10503                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10504         else
10505                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10506
10507         wrapperm = (MonoMethodWrapper*)m;
10508
10509         m->dynamic = dynamic;
10510         m->slot = -1;
10511         m->flags = rmb->attrs;
10512         m->iflags = rmb->iattrs;
10513         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10514         m->klass = klass;
10515         m->signature = sig;
10516         m->sre_method = TRUE;
10517         m->skip_visibility = rmb->skip_visibility;
10518         if (rmb->table_idx)
10519                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10520
10521         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10522                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10523                         m->string_ctor = 1;
10524
10525                 m->signature->pinvoke = 1;
10526         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10527                 m->signature->pinvoke = 1;
10528
10529                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10530
10531                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10532                 g_assert (mono_error_ok (&error));
10533                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10534                 g_assert (mono_error_ok (&error));
10535                 
10536                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10537
10538                 if (image_is_dynamic (klass->image))
10539                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10540
10541                 mono_loader_unlock ();
10542
10543                 return m;
10544         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10545                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10546                 MonoMethodHeader *header;
10547                 guint32 code_size;
10548                 gint32 max_stack, i;
10549                 gint32 num_locals = 0;
10550                 gint32 num_clauses = 0;
10551                 guint8 *code;
10552
10553                 if (rmb->ilgen) {
10554                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10555                         code_size = rmb->ilgen->code_len;
10556                         max_stack = rmb->ilgen->max_stack;
10557                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10558                         if (rmb->ilgen->ex_handlers)
10559                                 num_clauses = method_count_clauses (rmb->ilgen);
10560                 } else {
10561                         if (rmb->code) {
10562                                 code = mono_array_addr (rmb->code, guint8, 0);
10563                                 code_size = mono_array_length (rmb->code);
10564                                 /* we probably need to run a verifier on the code... */
10565                                 max_stack = 8; 
10566                         }
10567                         else {
10568                                 code = NULL;
10569                                 code_size = 0;
10570                                 max_stack = 8;
10571                         }
10572                 }
10573
10574                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10575                 header->code_size = code_size;
10576                 header->code = image_g_malloc (image, code_size);
10577                 memcpy ((char*)header->code, code, code_size);
10578                 header->max_stack = max_stack;
10579                 header->init_locals = rmb->init_locals;
10580                 header->num_locals = num_locals;
10581
10582                 for (i = 0; i < num_locals; ++i) {
10583                         MonoReflectionLocalBuilder *lb = 
10584                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10585
10586                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10587                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10588                 }
10589
10590                 header->num_clauses = num_clauses;
10591                 if (num_clauses) {
10592                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10593                                  rmb->ilgen, num_clauses);
10594                 }
10595
10596                 wrapperm->header = header;
10597         }
10598
10599         if (rmb->generic_params) {
10600                 int count = mono_array_length (rmb->generic_params);
10601                 MonoGenericContainer *container = rmb->generic_container;
10602
10603                 g_assert (container);
10604
10605                 container->type_argc = count;
10606                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10607                 container->owner.method = m;
10608
10609                 m->is_generic = TRUE;
10610                 mono_method_set_generic_container (m, container);
10611
10612                 for (i = 0; i < count; i++) {
10613                         MonoReflectionGenericParam *gp =
10614                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10615                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10616                         container->type_params [i] = *param;
10617                 }
10618
10619                 /*
10620                  * The method signature might have pointers to generic parameters that belong to other methods.
10621                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10622                  * generic parameters.
10623                  */
10624                 for (i = 0; i < m->signature->param_count; ++i) {
10625                         MonoType *t = m->signature->params [i];
10626                         if (t->type == MONO_TYPE_MVAR) {
10627                                 MonoGenericParam *gparam =  t->data.generic_param;
10628                                 if (gparam->num < count) {
10629                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10630                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10631                                 }
10632
10633                         }
10634                 }
10635
10636                 if (klass->generic_container) {
10637                         container->parent = klass->generic_container;
10638                         container->context.class_inst = klass->generic_container->context.class_inst;
10639                 }
10640                 container->context.method_inst = mono_get_shared_generic_inst (container);
10641         }
10642
10643         if (rmb->refs) {
10644                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10645                 int i;
10646                 void **data;
10647
10648                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10649
10650                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10651                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10652                 for (i = 0; i < rmb->nrefs; ++i)
10653                         data [i + 1] = rmb->refs [i];
10654         }
10655
10656         method_aux = NULL;
10657
10658         /* Parameter info */
10659         if (rmb->pinfo) {
10660                 if (!method_aux)
10661                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10662                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10663                 for (i = 0; i <= m->signature->param_count; ++i) {
10664                         MonoReflectionParamBuilder *pb;
10665                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10666                                 if ((i > 0) && (pb->attrs)) {
10667                                         /* Make a copy since it might point to a shared type structure */
10668                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10669                                         m->signature->params [i - 1]->attrs = pb->attrs;
10670                                 }
10671
10672                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10673                                         MonoDynamicImage *assembly;
10674                                         guint32 idx, def_type, len;
10675                                         char *p;
10676                                         const char *p2;
10677
10678                                         if (!method_aux->param_defaults) {
10679                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10680                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10681                                         }
10682                                         assembly = (MonoDynamicImage*)klass->image;
10683                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10684                                         /* Copy the data from the blob since it might get realloc-ed */
10685                                         p = assembly->blob.data + idx;
10686                                         len = mono_metadata_decode_blob_size (p, &p2);
10687                                         len += p2 - p;
10688                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10689                                         method_aux->param_default_types [i] = def_type;
10690                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10691                                 }
10692
10693                                 if (pb->name) {
10694                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10695                                         g_assert (mono_error_ok (&error));
10696                                 }
10697                                 if (pb->cattrs) {
10698                                         if (!method_aux->param_cattr)
10699                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10700                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10701                                 }
10702                         }
10703                 }
10704         }
10705
10706         /* Parameter marshalling */
10707         specs = NULL;
10708         if (rmb->pinfo)         
10709                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10710                         MonoReflectionParamBuilder *pb;
10711                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10712                                 if (pb->marshal_info) {
10713                                         if (specs == NULL)
10714                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10715                                         specs [pb->position] = 
10716                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10717                                 }
10718                         }
10719                 }
10720         if (specs != NULL) {
10721                 if (!method_aux)
10722                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10723                 method_aux->param_marshall = specs;
10724         }
10725
10726         if (image_is_dynamic (klass->image) && method_aux)
10727                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10728
10729         mono_loader_unlock ();
10730
10731         return m;
10732 }       
10733
10734 static MonoMethod*
10735 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10736 {
10737         ReflectionMethodBuilder rmb;
10738         MonoMethodSignature *sig;
10739
10740         mono_loader_lock ();
10741         sig = ctor_builder_to_signature (klass->image, mb);
10742         mono_loader_unlock ();
10743
10744         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10745
10746         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10747         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10748
10749         /* If we are in a generic class, we might be called multiple times from inflate_method */
10750         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10751                 /* ilgen is no longer needed */
10752                 mb->ilgen = NULL;
10753         }
10754
10755         return mb->mhandle;
10756 }
10757
10758 static MonoMethod*
10759 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10760 {
10761         ReflectionMethodBuilder rmb;
10762         MonoMethodSignature *sig;
10763
10764         mono_loader_lock ();
10765         sig = method_builder_to_signature (klass->image, mb);
10766         mono_loader_unlock ();
10767
10768         reflection_methodbuilder_from_method_builder (&rmb, mb);
10769
10770         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10771         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10772
10773         /* If we are in a generic class, we might be called multiple times from inflate_method */
10774         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10775                 /* ilgen is no longer needed */
10776                 mb->ilgen = NULL;
10777         }
10778         return mb->mhandle;
10779 }
10780
10781 static MonoClassField*
10782 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10783 {
10784         MonoClassField *field;
10785         MonoType *custom;
10786         MonoError error;
10787
10788         field = g_new0 (MonoClassField, 1);
10789
10790         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10791         g_assert (mono_error_ok (&error));
10792         if (fb->attrs || fb->modreq || fb->modopt) {
10793                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10794                 field->type->attrs = fb->attrs;
10795
10796                 g_assert (image_is_dynamic (klass->image));
10797                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10798                 g_free (field->type);
10799                 field->type = mono_metadata_type_dup (klass->image, custom);
10800                 g_free (custom);
10801         } else {
10802                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10803         }
10804         if (fb->offset != -1)
10805                 field->offset = fb->offset;
10806         field->parent = klass;
10807         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10808
10809         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10810
10811         return field;
10812 }
10813 #endif
10814
10815 MonoType*
10816 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10817 {
10818         MonoClass *klass;
10819         MonoReflectionTypeBuilder *tb = NULL;
10820         gboolean is_dynamic = FALSE;
10821         MonoClass *geninst;
10822
10823         mono_loader_lock ();
10824
10825         if (is_sre_type_builder (mono_object_class (type))) {
10826                 tb = (MonoReflectionTypeBuilder *) type;
10827
10828                 is_dynamic = TRUE;
10829         } else if (is_sre_generic_instance (mono_object_class (type))) {
10830                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10831                 MonoReflectionType *gtd = rgi->generic_type;
10832
10833                 if (is_sre_type_builder (mono_object_class (gtd))) {
10834                         tb = (MonoReflectionTypeBuilder *)gtd;
10835                         is_dynamic = TRUE;
10836                 }
10837         }
10838
10839         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10840         if (tb && tb->generic_container)
10841                 mono_reflection_create_generic_class (tb);
10842
10843         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10844         if (!klass->generic_container) {
10845                 mono_loader_unlock ();
10846                 return NULL;
10847         }
10848
10849         if (klass->wastypebuilder) {
10850                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10851
10852                 is_dynamic = TRUE;
10853         }
10854
10855         mono_loader_unlock ();
10856
10857         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10858
10859         return &geninst->byval_arg;
10860 }
10861
10862 MonoClass*
10863 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10864 {
10865         MonoGenericClass *gclass;
10866         MonoGenericInst *inst;
10867
10868         g_assert (klass->generic_container);
10869
10870         inst = mono_metadata_get_generic_inst (type_argc, types);
10871         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10872
10873         return mono_generic_class_get_class (gclass);
10874 }
10875
10876 MonoReflectionMethod*
10877 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10878 {
10879         MonoError error;
10880         MonoClass *klass;
10881         MonoMethod *method, *inflated;
10882         MonoMethodInflated *imethod;
10883         MonoGenericContext tmp_context;
10884         MonoGenericInst *ginst;
10885         MonoType **type_argv;
10886         int count, i;
10887
10888         /*FIXME but this no longer should happen*/
10889         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10890 #ifndef DISABLE_REFLECTION_EMIT
10891                 MonoReflectionMethodBuilder *mb = NULL;
10892                 MonoReflectionTypeBuilder *tb;
10893                 MonoClass *klass;
10894
10895                 mb = (MonoReflectionMethodBuilder *) rmethod;
10896                 tb = (MonoReflectionTypeBuilder *) mb->type;
10897                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10898
10899                 method = methodbuilder_to_mono_method (klass, mb);
10900 #else
10901                 g_assert_not_reached ();
10902                 method = NULL;
10903 #endif
10904         } else {
10905                 method = rmethod->method;
10906         }
10907
10908         klass = method->klass;
10909
10910         if (method->is_inflated)
10911                 method = ((MonoMethodInflated *) method)->declaring;
10912
10913         count = mono_method_signature (method)->generic_param_count;
10914         if (count != mono_array_length (types))
10915                 return NULL;
10916
10917         type_argv = g_new0 (MonoType *, count);
10918         for (i = 0; i < count; i++) {
10919                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10920                 type_argv [i] = mono_reflection_type_get_handle (garg);
10921         }
10922         ginst = mono_metadata_get_generic_inst (count, type_argv);
10923         g_free (type_argv);
10924
10925         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10926         tmp_context.method_inst = ginst;
10927
10928         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
10929         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10930         imethod = (MonoMethodInflated *) inflated;
10931
10932         /*FIXME but I think this is no longer necessary*/
10933         if (image_is_dynamic (method->klass->image)) {
10934                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10935                 /*
10936                  * This table maps metadata structures representing inflated methods/fields
10937                  * to the reflection objects representing their generic definitions.
10938                  */
10939                 mono_image_lock ((MonoImage*)image);
10940                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10941                 mono_image_unlock ((MonoImage*)image);
10942         }
10943
10944         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10945                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10946         
10947         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10948 }
10949
10950 #ifndef DISABLE_REFLECTION_EMIT
10951
10952 static MonoMethod *
10953 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10954 {
10955         MonoMethodInflated *imethod;
10956         MonoGenericContext *context;
10957         int i;
10958
10959         /*
10960          * With generic code sharing the klass might not be inflated.
10961          * This can happen because classes inflated with their own
10962          * type arguments are "normalized" to the uninflated class.
10963          */
10964         if (!klass->generic_class)
10965                 return method;
10966
10967         context = mono_class_get_context (klass);
10968
10969         if (klass->method.count && klass->methods) {
10970                 /* Find the already created inflated method */
10971                 for (i = 0; i < klass->method.count; ++i) {
10972                         g_assert (klass->methods [i]->is_inflated);
10973                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10974                                 break;
10975                 }
10976                 g_assert (i < klass->method.count);
10977                 imethod = (MonoMethodInflated*)klass->methods [i];
10978         } else {
10979                 MonoError error;
10980                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
10981                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10982         }
10983
10984         if (method->is_generic && image_is_dynamic (method->klass->image)) {
10985                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10986
10987                 mono_image_lock ((MonoImage*)image);
10988                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10989                 mono_image_unlock ((MonoImage*)image);
10990         }
10991         return (MonoMethod *) imethod;
10992 }
10993
10994 static MonoMethod *
10995 inflate_method (MonoReflectionType *type, MonoObject *obj)
10996 {
10997         MonoMethod *method;
10998         MonoClass *gklass;
10999
11000         MonoClass *type_class = mono_object_class (type);
11001
11002         if (is_sre_generic_instance (type_class)) {
11003                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11004                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11005         } else if (is_sre_type_builder (type_class)) {
11006                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11007         } else if (type->type) {
11008                 gklass = mono_class_from_mono_type (type->type);
11009                 gklass = mono_class_get_generic_type_definition (gklass);
11010         } else {
11011                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11012         }
11013
11014         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11015                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11016                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11017                 else
11018                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11019         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11020                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11021         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11022                 method = ((MonoReflectionMethod *) obj)->method;
11023         else {
11024                 method = NULL; /* prevent compiler warning */
11025                 g_error ("can't handle type %s", obj->vtable->klass->name);
11026         }
11027
11028         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11029 }
11030
11031 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11032 void
11033 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11034 {
11035         MonoGenericClass *gclass;
11036         MonoDynamicGenericClass *dgclass;
11037         MonoClass *klass, *gklass;
11038         MonoType *gtype;
11039         int i;
11040
11041         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11042         klass = mono_class_from_mono_type (gtype);
11043         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11044         gclass = gtype->data.generic_class;
11045
11046         if (!gclass->is_dynamic)
11047                 return;
11048
11049         dgclass = (MonoDynamicGenericClass *) gclass;
11050
11051         if (dgclass->initialized)
11052                 return;
11053
11054         gklass = gclass->container_class;
11055         mono_class_init (gklass);
11056
11057         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11058
11059         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11060         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11061         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11062
11063         for (i = 0; i < dgclass->count_fields; i++) {
11064                 MonoObject *obj = mono_array_get (fields, gpointer, i);
11065                 MonoClassField *field, *inflated_field = NULL;
11066
11067                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11068                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11069                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11070                         field = ((MonoReflectionField *) obj)->field;
11071                 else {
11072                         field = NULL; /* prevent compiler warning */
11073                         g_assert_not_reached ();
11074                 }
11075
11076                 dgclass->fields [i] = *field;
11077                 dgclass->fields [i].parent = klass;
11078                 dgclass->fields [i].type = mono_class_inflate_generic_type (
11079                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11080                 dgclass->field_generic_types [i] = field->type;
11081                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11082                 dgclass->field_objects [i] = obj;
11083
11084                 if (inflated_field) {
11085                         g_free (inflated_field);
11086                 } else {
11087                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11088                 }
11089         }
11090
11091         dgclass->initialized = TRUE;
11092 }
11093
11094 void
11095 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11096 {
11097         MonoDynamicGenericClass *dgclass;
11098         int i;
11099
11100         g_assert (gclass->is_dynamic);
11101
11102         dgclass = (MonoDynamicGenericClass *)gclass;
11103
11104         for (i = 0; i < dgclass->count_fields; ++i) {
11105                 MonoClassField *field = dgclass->fields + i;
11106                 mono_metadata_free_type (field->type);
11107                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11108         }
11109 }
11110
11111 static void
11112 fix_partial_generic_class (MonoClass *klass)
11113 {
11114         MonoClass *gklass = klass->generic_class->container_class;
11115         MonoDynamicGenericClass *dgclass;
11116         int i;
11117
11118         if (klass->wastypebuilder)
11119                 return;
11120
11121         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11122         if (klass->parent != gklass->parent) {
11123                 MonoError error;
11124                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11125                 if (mono_error_ok (&error)) {
11126                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11127                         mono_metadata_free_type (parent_type);
11128                         if (parent != klass->parent) {
11129                                 /*fool mono_class_setup_parent*/
11130                                 klass->supertypes = NULL;
11131                                 mono_class_setup_parent (klass, parent);
11132                         }
11133                 } else {
11134                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11135                         mono_error_cleanup (&error);
11136                         if (gklass->wastypebuilder)
11137                                 klass->wastypebuilder = TRUE;
11138                         return;
11139                 }
11140         }
11141
11142         if (!dgclass->initialized)
11143                 return;
11144
11145         if (klass->method.count != gklass->method.count) {
11146                 klass->method.count = gklass->method.count;
11147                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11148
11149                 for (i = 0; i < klass->method.count; i++) {
11150                         MonoError error;
11151                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11152                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11153                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11154                 }
11155         }
11156
11157         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11158                 klass->interface_count = gklass->interface_count;
11159                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11160                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11161
11162                 for (i = 0; i < gklass->interface_count; ++i) {
11163                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11164                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11165                         mono_metadata_free_type (iface_type);
11166
11167                         ensure_runtime_vtable (klass->interfaces [i]);
11168                 }
11169                 klass->interfaces_inited = 1;
11170         }
11171
11172         if (klass->field.count != gklass->field.count) {
11173                 klass->field.count = gklass->field.count;
11174                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11175
11176                 for (i = 0; i < klass->field.count; i++) {
11177                         klass->fields [i] = gklass->fields [i];
11178                         klass->fields [i].parent = klass;
11179                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11180                 }
11181         }
11182
11183         /*We can only finish with this klass once it's parent has as well*/
11184         if (gklass->wastypebuilder)
11185                 klass->wastypebuilder = TRUE;
11186         return;
11187 }
11188
11189 static void
11190 ensure_generic_class_runtime_vtable (MonoClass *klass)
11191 {
11192         MonoClass *gklass = klass->generic_class->container_class;
11193
11194         ensure_runtime_vtable (gklass); 
11195
11196         fix_partial_generic_class (klass);
11197 }
11198
11199 static void
11200 ensure_runtime_vtable (MonoClass *klass)
11201 {
11202         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11203         int i, num, j;
11204
11205         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11206                 return;
11207         if (klass->parent)
11208                 ensure_runtime_vtable (klass->parent);
11209
11210         if (tb) {
11211                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11212                 num += tb->num_methods;
11213                 klass->method.count = num;
11214                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11215                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11216                 for (i = 0; i < num; ++i)
11217                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11218                 num = tb->num_methods;
11219                 j = i;
11220                 for (i = 0; i < num; ++i)
11221                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11222         
11223                 if (tb->interfaces) {
11224                         klass->interface_count = mono_array_length (tb->interfaces);
11225                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11226                         for (i = 0; i < klass->interface_count; ++i) {
11227                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11228                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11229                                 ensure_runtime_vtable (klass->interfaces [i]);
11230                         }
11231                         klass->interfaces_inited = 1;
11232                 }
11233         } else if (klass->generic_class){
11234                 ensure_generic_class_runtime_vtable (klass);
11235         }
11236
11237         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11238                 int slot_num = 0;
11239                 for (i = 0; i < klass->method.count; ++i) {
11240                         MonoMethod *im = klass->methods [i];
11241                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11242                                 im->slot = slot_num++;
11243                 }
11244                 
11245                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11246                 mono_class_setup_interface_offsets (klass);
11247                 mono_class_setup_interface_id (klass);
11248         }
11249
11250         /*
11251          * The generic vtable is needed even if image->run is not set since some
11252          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11253          * method->slot being defined.
11254          */
11255
11256         /* 
11257          * tb->methods could not be freed since it is used for determining 
11258          * overrides during dynamic vtable construction.
11259          */
11260 }
11261
11262 static MonoMethod*
11263 mono_reflection_method_get_handle (MonoObject *method)
11264 {
11265         MonoClass *class = mono_object_class (method);
11266         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
11267                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11268                 return sr_method->method;
11269         }
11270         if (is_sre_method_builder (class)) {
11271                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11272                 return mb->mhandle;
11273         }
11274         if (is_sre_method_on_tb_inst (class)) {
11275                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11276                 MonoMethod *result;
11277                 /*FIXME move this to a proper method and unify with resolve_object*/
11278                 if (m->method_args) {
11279                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11280                 } else {
11281                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11282                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11283                         MonoMethod *mono_method;
11284
11285                         if (is_sre_method_builder (mono_object_class (m->mb)))
11286                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11287                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11288                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11289                         else
11290                                 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)));
11291
11292                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11293                 }
11294                 return result;
11295         }
11296
11297         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
11298         return NULL;
11299 }
11300
11301 void
11302 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11303 {
11304         MonoReflectionTypeBuilder *tb;
11305         int i, j, onum;
11306         MonoReflectionMethod *m;
11307
11308         *overrides = NULL;
11309         *num_overrides = 0;
11310
11311         g_assert (image_is_dynamic (klass->image));
11312
11313         if (!mono_class_get_ref_info (klass))
11314                 return;
11315
11316         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11317
11318         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11319
11320         onum = 0;
11321         if (tb->methods) {
11322                 for (i = 0; i < tb->num_methods; ++i) {
11323                         MonoReflectionMethodBuilder *mb = 
11324                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11325                         if (mb->override_methods)
11326                                 onum += mono_array_length (mb->override_methods);
11327                 }
11328         }
11329
11330         if (onum) {
11331                 *overrides = g_new0 (MonoMethod*, onum * 2);
11332
11333                 onum = 0;
11334                 for (i = 0; i < tb->num_methods; ++i) {
11335                         MonoReflectionMethodBuilder *mb = 
11336                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11337                         if (mb->override_methods) {
11338                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11339                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11340
11341                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11342                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11343
11344                                         g_assert (mb->mhandle);
11345
11346                                         onum ++;
11347                                 }
11348                         }
11349                 }
11350         }
11351
11352         *num_overrides = onum;
11353 }
11354
11355 static void
11356 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11357 {
11358         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11359         MonoReflectionFieldBuilder *fb;
11360         MonoClassField *field;
11361         MonoImage *image = klass->image;
11362         const char *p, *p2;
11363         int i;
11364         guint32 len, idx, real_size = 0;
11365
11366         klass->field.count = tb->num_fields;
11367         klass->field.first = 0;
11368
11369         mono_error_init (error);
11370
11371         if (tb->class_size) {
11372                 if ((tb->packing_size & 0xffffff00) != 0) {
11373                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11374                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11375                         return;
11376                 }
11377                 klass->packing_size = tb->packing_size;
11378                 real_size = klass->instance_size + tb->class_size;
11379         }
11380
11381         if (!klass->field.count) {
11382                 klass->instance_size = MAX (klass->instance_size, real_size);
11383                 return;
11384         }
11385         
11386         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11387         mono_class_alloc_ext (klass);
11388         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11389         /*
11390         This is, guess what, a hack.
11391         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11392         On the static path no field class is resolved, only types are built. This is the right thing to do
11393         but we suck.
11394         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11395         */
11396         klass->size_inited = 1;
11397
11398         for (i = 0; i < klass->field.count; ++i) {
11399                 MonoArray *rva_data;
11400                 fb = mono_array_get (tb->fields, gpointer, i);
11401                 field = &klass->fields [i];
11402                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11403                 if (!mono_error_ok (error))
11404                         return;
11405                 if (fb->attrs) {
11406                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11407                         field->type->attrs = fb->attrs;
11408                 } else {
11409                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11410                 }
11411
11412                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11413                         char *base = mono_array_addr (rva_data, char, 0);
11414                         size_t size = mono_array_length (rva_data);
11415                         char *data = mono_image_alloc (klass->image, size);
11416                         memcpy (data, base, size);
11417                         klass->ext->field_def_values [i].data = data;
11418                 }
11419                 if (fb->offset != -1)
11420                         field->offset = fb->offset;
11421                 field->parent = klass;
11422                 fb->handle = field;
11423                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11424
11425                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11426                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11427                 }
11428                 if (fb->def_value) {
11429                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11430                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11431                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11432                         /* Copy the data from the blob since it might get realloc-ed */
11433                         p = assembly->blob.data + idx;
11434                         len = mono_metadata_decode_blob_size (p, &p2);
11435                         len += p2 - p;
11436                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11437                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11438                 }
11439         }
11440
11441         klass->instance_size = MAX (klass->instance_size, real_size);
11442         mono_class_layout_fields (klass);
11443 }
11444
11445 static void
11446 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11447 {
11448         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11449         MonoReflectionPropertyBuilder *pb;
11450         MonoImage *image = klass->image;
11451         MonoProperty *properties;
11452         int i;
11453
11454         mono_error_init (error);
11455
11456         if (!klass->ext)
11457                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11458
11459         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11460         klass->ext->property.first = 0;
11461
11462         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11463         klass->ext->properties = properties;
11464         for (i = 0; i < klass->ext->property.count; ++i) {
11465                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11466                 properties [i].parent = klass;
11467                 properties [i].attrs = pb->attrs;
11468                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11469                 if (!mono_error_ok (error))
11470                         return;
11471                 if (pb->get_method)
11472                         properties [i].get = pb->get_method->mhandle;
11473                 if (pb->set_method)
11474                         properties [i].set = pb->set_method->mhandle;
11475
11476                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11477                 if (pb->def_value) {
11478                         guint32 len, idx;
11479                         const char *p, *p2;
11480                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11481                         if (!klass->ext->prop_def_values)
11482                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11483                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11484                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11485                         /* Copy the data from the blob since it might get realloc-ed */
11486                         p = assembly->blob.data + idx;
11487                         len = mono_metadata_decode_blob_size (p, &p2);
11488                         len += p2 - p;
11489                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11490                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11491                 }
11492         }
11493 }
11494
11495 MonoReflectionEvent *
11496 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11497 {
11498         MonoEvent *event = g_new0 (MonoEvent, 1);
11499         MonoClass *klass;
11500
11501         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11502
11503         event->parent = klass;
11504         event->attrs = eb->attrs;
11505         event->name = mono_string_to_utf8 (eb->name);
11506         if (eb->add_method)
11507                 event->add = eb->add_method->mhandle;
11508         if (eb->remove_method)
11509                 event->remove = eb->remove_method->mhandle;
11510         if (eb->raise_method)
11511                 event->raise = eb->raise_method->mhandle;
11512
11513 #ifndef MONO_SMALL_CONFIG
11514         if (eb->other_methods) {
11515                 int j;
11516                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11517                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11518                         MonoReflectionMethodBuilder *mb = 
11519                                 mono_array_get (eb->other_methods,
11520                                                 MonoReflectionMethodBuilder*, j);
11521                         event->other [j] = mb->mhandle;
11522                 }
11523         }
11524 #endif
11525
11526         return mono_event_get_object (mono_object_domain (tb), klass, event);
11527 }
11528
11529 static void
11530 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11531 {
11532         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11533         MonoReflectionEventBuilder *eb;
11534         MonoImage *image = klass->image;
11535         MonoEvent *events;
11536         int i;
11537
11538         mono_error_init (error);
11539
11540         if (!klass->ext)
11541                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11542
11543         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11544         klass->ext->event.first = 0;
11545
11546         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11547         klass->ext->events = events;
11548         for (i = 0; i < klass->ext->event.count; ++i) {
11549                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11550                 events [i].parent = klass;
11551                 events [i].attrs = eb->attrs;
11552                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11553                 if (!mono_error_ok (error))
11554                         return;
11555                 if (eb->add_method)
11556                         events [i].add = eb->add_method->mhandle;
11557                 if (eb->remove_method)
11558                         events [i].remove = eb->remove_method->mhandle;
11559                 if (eb->raise_method)
11560                         events [i].raise = eb->raise_method->mhandle;
11561
11562 #ifndef MONO_SMALL_CONFIG
11563                 if (eb->other_methods) {
11564                         int j;
11565                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11566                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11567                                 MonoReflectionMethodBuilder *mb = 
11568                                         mono_array_get (eb->other_methods,
11569                                                                         MonoReflectionMethodBuilder*, j);
11570                                 events [i].other [j] = mb->mhandle;
11571                         }
11572                 }
11573 #endif
11574                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11575         }
11576 }
11577
11578 static gboolean
11579 remove_instantiations_of_and_ensure_contents (gpointer key,
11580                                                   gpointer value,
11581                                                   gpointer user_data)
11582 {
11583         MonoType *type = (MonoType*)key;
11584         MonoClass *klass = (MonoClass*)user_data;
11585
11586         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11587                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11588                 return TRUE;
11589         } else
11590                 return FALSE;
11591 }
11592
11593 static void
11594 check_array_for_usertypes (MonoArray *arr)
11595 {
11596         int i;
11597
11598         if (!arr)
11599                 return;
11600
11601         for (i = 0; i < mono_array_length (arr); ++i)
11602                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11603 }
11604
11605 MonoReflectionType*
11606 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11607 {
11608         MonoError error;
11609         MonoClass *klass;
11610         MonoDomain* domain;
11611         MonoReflectionType* res;
11612         int i, j;
11613
11614         domain = mono_object_domain (tb);
11615         klass = mono_class_from_mono_type (tb->type.type);
11616
11617         /*
11618          * Check for user defined Type subclasses.
11619          */
11620         RESOLVE_TYPE (tb->parent);
11621         check_array_for_usertypes (tb->interfaces);
11622         if (tb->fields) {
11623                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11624                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11625                         if (fb) {
11626                                 RESOLVE_TYPE (fb->type);
11627                                 check_array_for_usertypes (fb->modreq);
11628                                 check_array_for_usertypes (fb->modopt);
11629                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11630                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11631                         }
11632                 }
11633         }
11634         if (tb->methods) {
11635                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11636                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11637                         if (mb) {
11638                                 RESOLVE_TYPE (mb->rtype);
11639                                 check_array_for_usertypes (mb->return_modreq);
11640                                 check_array_for_usertypes (mb->return_modopt);
11641                                 check_array_for_usertypes (mb->parameters);
11642                                 if (mb->param_modreq)
11643                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11644                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11645                                 if (mb->param_modopt)
11646                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11647                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11648                         }
11649                 }
11650         }
11651         if (tb->ctors) {
11652                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11653                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11654                         if (mb) {
11655                                 check_array_for_usertypes (mb->parameters);
11656                                 if (mb->param_modreq)
11657                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11658                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11659                                 if (mb->param_modopt)
11660                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11661                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11662                         }
11663                 }
11664         }
11665
11666         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11667
11668         /* 
11669          * we need to lock the domain because the lock will be taken inside
11670          * So, we need to keep the locking order correct.
11671          */
11672         mono_loader_lock ();
11673         mono_domain_lock (domain);
11674         if (klass->wastypebuilder) {
11675                 mono_domain_unlock (domain);
11676                 mono_loader_unlock ();
11677                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11678         }
11679         /*
11680          * Fields to set in klass:
11681          * the various flags: delegate/unicode/contextbound etc.
11682          */
11683         klass->flags = tb->attrs;
11684         klass->has_cctor = 1;
11685         klass->has_finalize = 1;
11686         klass->has_finalize_inited = 1;
11687
11688         mono_class_setup_parent (klass, klass->parent);
11689         /* fool mono_class_setup_supertypes */
11690         klass->supertypes = NULL;
11691         mono_class_setup_supertypes (klass);
11692         mono_class_setup_mono_type (klass);
11693
11694 #if 0
11695         if (!((MonoDynamicImage*)klass->image)->run) {
11696                 if (klass->generic_container) {
11697                         /* FIXME: The code below can't handle generic classes */
11698                         klass->wastypebuilder = TRUE;
11699                         mono_loader_unlock ();
11700                         mono_domain_unlock (domain);
11701                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11702                 }
11703         }
11704 #endif
11705
11706         /* enums are done right away */
11707         if (!klass->enumtype)
11708                 ensure_runtime_vtable (klass);
11709
11710         if (tb->subtypes) {
11711                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11712                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11713                         mono_class_alloc_ext (klass);
11714                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)subtb)));
11715                 }
11716         }
11717
11718         klass->nested_classes_inited = TRUE;
11719
11720         /* fields and object layout */
11721         if (klass->parent) {
11722                 if (!klass->parent->size_inited)
11723                         mono_class_init (klass->parent);
11724                 klass->instance_size = klass->parent->instance_size;
11725                 klass->sizes.class_size = 0;
11726                 klass->min_align = klass->parent->min_align;
11727                 /* if the type has no fields we won't call the field_setup
11728                  * routine which sets up klass->has_references.
11729                  */
11730                 klass->has_references |= klass->parent->has_references;
11731         } else {
11732                 klass->instance_size = sizeof (MonoObject);
11733                 klass->min_align = 1;
11734         }
11735
11736         /* FIXME: handle packing_size and instance_size */
11737         typebuilder_setup_fields (klass, &error);
11738         if (!mono_error_ok (&error))
11739                 goto failure;
11740         typebuilder_setup_properties (klass, &error);
11741         if (!mono_error_ok (&error))
11742                 goto failure;
11743
11744         typebuilder_setup_events (klass, &error);
11745         if (!mono_error_ok (&error))
11746                 goto failure;
11747
11748         klass->wastypebuilder = TRUE;
11749
11750         /* 
11751          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11752          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11753          * we want to return normal System.MonoType objects, so clear these out from the cache.
11754          *
11755          * Together with this we must ensure the contents of all instances to match the created type.
11756          */
11757         if (domain->type_hash && klass->generic_container)
11758                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11759
11760         mono_domain_unlock (domain);
11761         mono_loader_unlock ();
11762
11763         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11764                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11765                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11766         }
11767
11768         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11769         g_assert (res != (MonoReflectionType*)tb);
11770
11771         return res;
11772
11773 failure:
11774         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11775         klass->wastypebuilder = TRUE;
11776         mono_domain_unlock (domain);
11777         mono_loader_unlock ();
11778         mono_error_raise_exception (&error);
11779         return NULL;
11780 }
11781
11782 void
11783 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11784 {
11785         MonoGenericParamFull *param;
11786         MonoImage *image;
11787         MonoClass *pklass;
11788         MonoError error;
11789
11790         image = &gparam->tbuilder->module->dynamic_image->image;
11791
11792         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11793
11794         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11795         g_assert (mono_error_ok (&error));
11796         param->param.num = gparam->index;
11797
11798         if (gparam->mbuilder) {
11799                 if (!gparam->mbuilder->generic_container) {
11800                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11801                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11802                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11803                         gparam->mbuilder->generic_container->is_method = TRUE;
11804                         /* 
11805                          * Cannot set owner.method, since the MonoMethod is not created yet.
11806                          * Set the image field instead, so type_in_image () works.
11807                          */
11808                         gparam->mbuilder->generic_container->image = klass->image;
11809                 }
11810                 param->param.owner = gparam->mbuilder->generic_container;
11811         } else if (gparam->tbuilder) {
11812                 if (!gparam->tbuilder->generic_container) {
11813                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11814                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11815                         gparam->tbuilder->generic_container->owner.klass = klass;
11816                 }
11817                 param->param.owner = gparam->tbuilder->generic_container;
11818         }
11819
11820         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11821
11822         gparam->type.type = &pklass->byval_arg;
11823
11824         mono_class_set_ref_info (pklass, gparam);
11825         mono_image_append_class_to_reflection_info_set (pklass);
11826 }
11827
11828 MonoArray *
11829 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11830 {
11831         MonoReflectionModuleBuilder *module = sig->module;
11832         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11833         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11834         guint32 buflen, i;
11835         MonoArray *result;
11836         SigBuffer buf;
11837
11838         check_array_for_usertypes (sig->arguments);
11839
11840         sigbuffer_init (&buf, 32);
11841
11842         sigbuffer_add_value (&buf, 0x07);
11843         sigbuffer_add_value (&buf, na);
11844         if (assembly != NULL){
11845                 for (i = 0; i < na; ++i) {
11846                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11847                         encode_reflection_type (assembly, type, &buf);
11848                 }
11849         }
11850
11851         buflen = buf.p - buf.buf;
11852         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11853         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11854         sigbuffer_free (&buf);
11855
11856         return result;
11857 }
11858
11859 MonoArray *
11860 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11861 {
11862         MonoDynamicImage *assembly = sig->module->dynamic_image;
11863         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11864         guint32 buflen, i;
11865         MonoArray *result;
11866         SigBuffer buf;
11867
11868         check_array_for_usertypes (sig->arguments);
11869
11870         sigbuffer_init (&buf, 32);
11871
11872         sigbuffer_add_value (&buf, 0x06);
11873         for (i = 0; i < na; ++i) {
11874                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11875                 encode_reflection_type (assembly, type, &buf);
11876         }
11877
11878         buflen = buf.p - buf.buf;
11879         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11880         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11881         sigbuffer_free (&buf);
11882
11883         return result;
11884 }
11885
11886 typedef struct {
11887         MonoMethod *handle;
11888         MonoDomain *domain;
11889 } DynamicMethodReleaseData;
11890
11891 /*
11892  * The runtime automatically clean up those after finalization.
11893 */      
11894 static MonoReferenceQueue *dynamic_method_queue;
11895
11896 static void
11897 free_dynamic_method (void *dynamic_method)
11898 {
11899         DynamicMethodReleaseData *data = dynamic_method;
11900         MonoDomain *domain = data->domain;
11901         MonoMethod *method = data->handle;
11902         guint32 dis_link;
11903
11904         mono_domain_lock (domain);
11905         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
11906         g_hash_table_remove (domain->method_to_dyn_method, method);
11907         mono_domain_unlock (domain);
11908         g_assert (dis_link);
11909         mono_gchandle_free (dis_link);
11910
11911         mono_runtime_free_method (domain, method);
11912         g_free (data);
11913 }
11914
11915 void 
11916 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11917 {
11918         MonoReferenceQueue *queue;
11919         MonoMethod *handle;
11920         DynamicMethodReleaseData *release_data;
11921         ReflectionMethodBuilder rmb;
11922         MonoMethodSignature *sig;
11923         MonoClass *klass;
11924         MonoDomain *domain;
11925         GSList *l;
11926         int i;
11927
11928         if (mono_runtime_is_shutting_down ())
11929                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11930
11931         if (!(queue = dynamic_method_queue)) {
11932                 mono_loader_lock ();
11933                 if (!(queue = dynamic_method_queue))
11934                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11935                 mono_loader_unlock ();
11936         }
11937
11938         sig = dynamic_method_to_signature (mb);
11939
11940         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11941
11942         /*
11943          * Resolve references.
11944          */
11945         /* 
11946          * Every second entry in the refs array is reserved for storing handle_class,
11947          * which is needed by the ldtoken implementation in the JIT.
11948          */
11949         rmb.nrefs = mb->nrefs;
11950         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11951         for (i = 0; i < mb->nrefs; i += 2) {
11952                 MonoClass *handle_class;
11953                 gpointer ref;
11954                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11955
11956                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11957                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11958                         /*
11959                          * The referenced DynamicMethod should already be created by the managed
11960                          * code, except in the case of circular references. In that case, we store
11961                          * method in the refs array, and fix it up later when the referenced 
11962                          * DynamicMethod is created.
11963                          */
11964                         if (method->mhandle) {
11965                                 ref = method->mhandle;
11966                         } else {
11967                                 /* FIXME: GC object stored in unmanaged memory */
11968                                 ref = method;
11969
11970                                 /* FIXME: GC object stored in unmanaged memory */
11971                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11972                         }
11973                         handle_class = mono_defaults.methodhandle_class;
11974                 } else {
11975                         MonoException *ex = NULL;
11976                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11977                         if (!ref)
11978                                 ex = mono_get_exception_type_load (NULL, NULL);
11979                         else if (mono_security_core_clr_enabled ())
11980                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11981
11982                         if (ex) {
11983                                 g_free (rmb.refs);
11984                                 mono_raise_exception (ex);
11985                                 return;
11986                         }
11987                 }
11988
11989                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11990                 rmb.refs [i + 1] = handle_class;
11991         }               
11992
11993         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11994
11995         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11996         release_data = g_new (DynamicMethodReleaseData, 1);
11997         release_data->handle = handle;
11998         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11999         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12000                 g_free (release_data);
12001
12002         /* Fix up refs entries pointing at us */
12003         for (l = mb->referenced_by; l; l = l->next) {
12004                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12005                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12006                 gpointer *data;
12007                 
12008                 g_assert (method->mhandle);
12009
12010                 data = (gpointer*)wrapper->method_data;
12011                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12012                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12013                                 data [i + 1] = mb->mhandle;
12014                 }
12015         }
12016         g_slist_free (mb->referenced_by);
12017
12018         g_free (rmb.refs);
12019
12020         /* ilgen is no longer needed */
12021         mb->ilgen = NULL;
12022
12023         domain = mono_domain_get ();
12024         mono_domain_lock (domain);
12025         if (!domain->method_to_dyn_method)
12026                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12027         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12028         mono_domain_unlock (domain);
12029 }
12030
12031 #endif /* DISABLE_REFLECTION_EMIT */
12032
12033 /**
12034  * 
12035  * mono_reflection_is_valid_dynamic_token:
12036  * 
12037  * Returns TRUE if token is valid.
12038  * 
12039  */
12040 gboolean
12041 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12042 {
12043         return lookup_dyn_token (image, token) != NULL;
12044 }
12045
12046 MonoMethodSignature *
12047 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12048 {
12049         MonoMethodSignature *sig;
12050         g_assert (image_is_dynamic (image));
12051
12052         mono_error_init (error);
12053
12054         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12055         if (sig)
12056                 return sig;
12057
12058         return mono_method_signature_checked (method, error);
12059 }
12060
12061 #ifndef DISABLE_REFLECTION_EMIT
12062
12063 /**
12064  * mono_reflection_lookup_dynamic_token:
12065  *
12066  * Finish the Builder object pointed to by TOKEN and return the corresponding
12067  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12068  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12069  * mapping table.
12070  *
12071  * LOCKING: Take the loader lock
12072  */
12073 gpointer
12074 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12075 {
12076         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12077         MonoObject *obj;
12078         MonoClass *klass;
12079
12080         obj = lookup_dyn_token (assembly, token);
12081         if (!obj) {
12082                 if (valid_token)
12083                         g_error ("Could not find required dynamic token 0x%08x", token);
12084                 else
12085                         return NULL;
12086         }
12087
12088         if (!handle_class)
12089                 handle_class = &klass;
12090         return resolve_object (image, obj, handle_class, context);
12091 }
12092
12093 /*
12094  * ensure_complete_type:
12095  *
12096  *   Ensure that KLASS is completed if it is a dynamic type, or references
12097  * dynamic types.
12098  */
12099 static void
12100 ensure_complete_type (MonoClass *klass)
12101 {
12102         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12103                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
12104
12105                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12106
12107                 // Asserting here could break a lot of code
12108                 //g_assert (klass->wastypebuilder);
12109         }
12110
12111         if (klass->generic_class) {
12112                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12113                 int i;
12114
12115                 for (i = 0; i < inst->type_argc; ++i) {
12116                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12117                 }
12118         }
12119 }
12120
12121 static gpointer
12122 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12123 {
12124         gpointer result = NULL;
12125
12126         if (strcmp (obj->vtable->klass->name, "String") == 0) {
12127                 result = mono_string_intern ((MonoString*)obj);
12128                 *handle_class = mono_defaults.string_class;
12129                 g_assert (result);
12130         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12131                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12132                 MonoClass *mc = mono_class_from_mono_type (type);
12133                 if (!mono_class_init (mc))
12134                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
12135
12136                 if (context) {
12137                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12138                         result = mono_class_from_mono_type (inflated);
12139                         mono_metadata_free_type (inflated);
12140                 } else {
12141                         result = mono_class_from_mono_type (type);
12142                 }
12143                 *handle_class = mono_defaults.typehandle_class;
12144                 g_assert (result);
12145         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12146                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12147                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12148                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12149                 result = ((MonoReflectionMethod*)obj)->method;
12150                 if (context) {
12151                         MonoError error;
12152                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12153                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12154                 }
12155                 *handle_class = mono_defaults.methodhandle_class;
12156                 g_assert (result);
12157         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12158                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12159                 result = mb->mhandle;
12160                 if (!result) {
12161                         /* Type is not yet created */
12162                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12163
12164                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12165
12166                         /*
12167                          * Hopefully this has been filled in by calling CreateType() on the
12168                          * TypeBuilder.
12169                          */
12170                         /*
12171                          * TODO: This won't work if the application finishes another 
12172                          * TypeBuilder instance instead of this one.
12173                          */
12174                         result = mb->mhandle;
12175                 }
12176                 if (context) {
12177                         MonoError error;
12178                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12179                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12180                 }
12181                 *handle_class = mono_defaults.methodhandle_class;
12182         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12183                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12184
12185                 result = cb->mhandle;
12186                 if (!result) {
12187                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12188
12189                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12190                         result = cb->mhandle;
12191                 }
12192                 if (context) {
12193                         MonoError error;
12194                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12195                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12196                 }
12197                 *handle_class = mono_defaults.methodhandle_class;
12198         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12199                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12200
12201                 ensure_complete_type (field->parent);
12202                 if (context) {
12203                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12204                         MonoClass *class = mono_class_from_mono_type (inflated);
12205                         MonoClassField *inflated_field;
12206                         gpointer iter = NULL;
12207                         mono_metadata_free_type (inflated);
12208                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
12209                                 if (!strcmp (field->name, inflated_field->name))
12210                                         break;
12211                         }
12212                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12213                         result = inflated_field;
12214                 } else {
12215                         result = field;
12216                 }
12217                 *handle_class = mono_defaults.fieldhandle_class;
12218                 g_assert (result);
12219         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12220                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12221                 result = fb->handle;
12222
12223                 if (!result) {
12224                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12225
12226                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12227                         result = fb->handle;
12228                 }
12229
12230                 if (fb->handle && fb->handle->parent->generic_container) {
12231                         MonoClass *klass = fb->handle->parent;
12232                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12233                         MonoClass *inflated = mono_class_from_mono_type (type);
12234
12235                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12236                         g_assert (result);
12237                         mono_metadata_free_type (type);
12238                 }
12239                 *handle_class = mono_defaults.fieldhandle_class;
12240         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12241                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12242                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12243                 MonoClass *klass;
12244
12245                 klass = type->data.klass;
12246                 if (klass->wastypebuilder) {
12247                         /* Already created */
12248                         result = klass;
12249                 }
12250                 else {
12251                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12252                         result = type->data.klass;
12253                         g_assert (result);
12254                 }
12255                 *handle_class = mono_defaults.typehandle_class;
12256         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12257                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12258                 MonoMethodSignature *sig;
12259                 int nargs, i;
12260
12261                 if (helper->arguments)
12262                         nargs = mono_array_length (helper->arguments);
12263                 else
12264                         nargs = 0;
12265
12266                 sig = mono_metadata_signature_alloc (image, nargs);
12267                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12268                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12269
12270                 if (helper->unmanaged_call_conv) { /* unmanaged */
12271                         sig->call_convention = helper->unmanaged_call_conv - 1;
12272                         sig->pinvoke = TRUE;
12273                 } else if (helper->call_conv & 0x02) {
12274                         sig->call_convention = MONO_CALL_VARARG;
12275                 } else {
12276                         sig->call_convention = MONO_CALL_DEFAULT;
12277                 }
12278
12279                 sig->param_count = nargs;
12280                 /* TODO: Copy type ? */
12281                 sig->ret = helper->return_type->type;
12282                 for (i = 0; i < nargs; ++i)
12283                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12284
12285                 result = sig;
12286                 *handle_class = NULL;
12287         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12288                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12289                 /* Already created by the managed code */
12290                 g_assert (method->mhandle);
12291                 result = method->mhandle;
12292                 *handle_class = mono_defaults.methodhandle_class;
12293         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12294                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12295                 type = mono_class_inflate_generic_type (type, context);
12296                 result = mono_class_from_mono_type (type);
12297                 *handle_class = mono_defaults.typehandle_class;
12298                 g_assert (result);
12299                 mono_metadata_free_type (type);
12300         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12301                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12302                 type = mono_class_inflate_generic_type (type, context);
12303                 result = mono_class_from_mono_type (type);
12304                 *handle_class = mono_defaults.typehandle_class;
12305                 g_assert (result);
12306                 mono_metadata_free_type (type);
12307         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12308                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12309                 MonoClass *inflated;
12310                 MonoType *type;
12311                 MonoClassField *field;
12312
12313                 if (is_sre_field_builder (mono_object_class (f->fb)))
12314                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12315                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12316                         field = ((MonoReflectionField*)f->fb)->field;
12317                 else
12318                         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)));
12319
12320                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12321                 inflated = mono_class_from_mono_type (type);
12322
12323                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12324                 ensure_complete_type (field->parent);
12325                 g_assert (result);
12326                 mono_metadata_free_type (type);
12327                 *handle_class = mono_defaults.fieldhandle_class;
12328         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12329                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12330                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12331                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12332                 MonoMethod *method;
12333
12334                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12335                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12336                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12337                         method = ((MonoReflectionMethod *)c->cb)->method;
12338                 else
12339                         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)));
12340
12341                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12342                 *handle_class = mono_defaults.methodhandle_class;
12343                 mono_metadata_free_type (type);
12344         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12345                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12346                 if (m->method_args) {
12347                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12348                         if (context) {
12349                                 MonoError error;
12350                                 result = mono_class_inflate_generic_method_checked (result, context, &error);
12351                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12352                         }
12353                 } else {
12354                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12355                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12356                         MonoMethod *method;
12357
12358                         if (is_sre_method_builder (mono_object_class (m->mb)))
12359                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12360                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12361                                 method = ((MonoReflectionMethod *)m->mb)->method;
12362                         else
12363                                 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)));
12364
12365                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12366                         mono_metadata_free_type (type);
12367                 }
12368                 *handle_class = mono_defaults.methodhandle_class;
12369         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12370                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12371                 MonoType *mtype;
12372                 MonoClass *klass;
12373                 MonoMethod *method;
12374                 gpointer iter;
12375                 char *name;
12376
12377                 mtype = mono_reflection_type_get_handle (m->parent);
12378                 klass = mono_class_from_mono_type (mtype);
12379
12380                 /* Find the method */
12381
12382                 name = mono_string_to_utf8 (m->name);
12383                 iter = NULL;
12384                 while ((method = mono_class_get_methods (klass, &iter))) {
12385                         if (!strcmp (method->name, name))
12386                                 break;
12387                 }
12388                 g_free (name);
12389
12390                 // FIXME:
12391                 g_assert (method);
12392                 // FIXME: Check parameters/return value etc. match
12393
12394                 result = method;
12395                 *handle_class = mono_defaults.methodhandle_class;
12396         } else if (is_sre_array (mono_object_get_class(obj)) ||
12397                                 is_sre_byref (mono_object_get_class(obj)) ||
12398                                 is_sre_pointer (mono_object_get_class(obj))) {
12399                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12400                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12401
12402                 if (context) {
12403                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12404                         result = mono_class_from_mono_type (inflated);
12405                         mono_metadata_free_type (inflated);
12406                 } else {
12407                         result = mono_class_from_mono_type (type);
12408                 }
12409                 *handle_class = mono_defaults.typehandle_class;
12410         } else {
12411                 g_print ("%s\n", obj->vtable->klass->name);
12412                 g_assert_not_reached ();
12413         }
12414         return result;
12415 }
12416
12417 #else /* DISABLE_REFLECTION_EMIT */
12418
12419 MonoArray*
12420 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12421 {
12422         g_assert_not_reached ();
12423         return NULL;
12424 }
12425
12426 void
12427 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12428 {
12429         g_assert_not_reached ();
12430 }
12431
12432 void
12433 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12434 {
12435         g_assert_not_reached ();
12436 }
12437
12438 void
12439 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12440 {
12441         g_assert_not_reached ();
12442 }
12443
12444 void
12445 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12446 {
12447         g_assert_not_reached ();
12448 }
12449
12450 void
12451 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12452 {
12453         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12454 }
12455
12456 void
12457 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12458 {
12459         g_assert_not_reached ();
12460 }
12461
12462 void
12463 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12464 {
12465         g_assert_not_reached ();
12466 }
12467
12468 MonoReflectionModule *
12469 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12470 {
12471         g_assert_not_reached ();
12472         return NULL;
12473 }
12474
12475 guint32
12476 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12477 {
12478         g_assert_not_reached ();
12479         return 0;
12480 }
12481
12482 guint32
12483 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12484 {
12485         g_assert_not_reached ();
12486         return 0;
12487 }
12488
12489 guint32
12490 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12491                                                  gboolean create_open_instance, gboolean register_token)
12492 {
12493         g_assert_not_reached ();
12494         return 0;
12495 }
12496
12497 void
12498 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12499 {
12500 }
12501
12502 void
12503 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12504 {
12505         g_assert_not_reached ();
12506 }
12507
12508 void
12509 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12510 {
12511         *overrides = NULL;
12512         *num_overrides = 0;
12513 }
12514
12515 MonoReflectionEvent *
12516 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12517 {
12518         g_assert_not_reached ();
12519         return NULL;
12520 }
12521
12522 MonoReflectionType*
12523 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12524 {
12525         g_assert_not_reached ();
12526         return NULL;
12527 }
12528
12529 void
12530 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12531 {
12532         g_assert_not_reached ();
12533 }
12534
12535 MonoArray *
12536 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12537 {
12538         g_assert_not_reached ();
12539         return NULL;
12540 }
12541
12542 MonoArray *
12543 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12544 {
12545         g_assert_not_reached ();
12546         return NULL;
12547 }
12548
12549 void 
12550 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12551 {
12552 }
12553
12554 gpointer
12555 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12556 {
12557         return NULL;
12558 }
12559
12560 MonoType*
12561 mono_reflection_type_get_handle (MonoReflectionType* ref)
12562 {
12563         if (!ref)
12564                 return NULL;
12565         return ref->type;
12566 }
12567
12568 void
12569 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12570 {
12571         g_assert_not_reached ();
12572 }
12573
12574 #endif /* DISABLE_REFLECTION_EMIT */
12575
12576 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12577 const static guint32 declsec_flags_map[] = {
12578         0x00000000,                                     /* empty */
12579         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12580         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12581         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12582         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12583         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12584         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12585         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12586         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12587         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12588         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12589         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12590         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12591         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12592         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12593         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12594         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12595         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12596         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12597 };
12598
12599 /*
12600  * Returns flags that includes all available security action associated to the handle.
12601  * @token: metadata token (either for a class or a method)
12602  * @image: image where resides the metadata.
12603  */
12604 static guint32
12605 mono_declsec_get_flags (MonoImage *image, guint32 token)
12606 {
12607         int index = mono_metadata_declsec_from_index (image, token);
12608         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12609         guint32 result = 0;
12610         guint32 action;
12611         int i;
12612
12613         /* HasSecurity can be present for other, not specially encoded, attributes,
12614            e.g. SuppressUnmanagedCodeSecurityAttribute */
12615         if (index < 0)
12616                 return 0;
12617
12618         for (i = index; i < t->rows; i++) {
12619                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12620
12621                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12622                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12623                         break;
12624
12625                 action = cols [MONO_DECL_SECURITY_ACTION];
12626                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12627                         result |= declsec_flags_map [action];
12628                 } else {
12629                         g_assert_not_reached ();
12630                 }
12631         }
12632         return result;
12633 }
12634
12635 /*
12636  * Get the security actions (in the form of flags) associated with the specified method.
12637  *
12638  * @method: The method for which we want the declarative security flags.
12639  * Return the declarative security flags for the method (only).
12640  *
12641  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12642  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12643  */
12644 guint32
12645 mono_declsec_flags_from_method (MonoMethod *method)
12646 {
12647         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12648                 /* FIXME: No cache (for the moment) */
12649                 guint32 idx = mono_method_get_index (method);
12650                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12651                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12652                 return mono_declsec_get_flags (method->klass->image, idx);
12653         }
12654         return 0;
12655 }
12656
12657 /*
12658  * Get the security actions (in the form of flags) associated with the specified class.
12659  *
12660  * @klass: The class for which we want the declarative security flags.
12661  * Return the declarative security flags for the class.
12662  *
12663  * Note: We cache the flags inside the MonoClass structure as this will get 
12664  *       called very often (at least for each method).
12665  */
12666 guint32
12667 mono_declsec_flags_from_class (MonoClass *klass)
12668 {
12669         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12670                 if (!klass->ext || !klass->ext->declsec_flags) {
12671                         guint32 idx;
12672
12673                         idx = mono_metadata_token_index (klass->type_token);
12674                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12675                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12676                         mono_loader_lock ();
12677                         mono_class_alloc_ext (klass);
12678                         mono_loader_unlock ();
12679                         /* we cache the flags on classes */
12680                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12681                 }
12682                 return klass->ext->declsec_flags;
12683         }
12684         return 0;
12685 }
12686
12687 /*
12688  * Get the security actions (in the form of flags) associated with the specified assembly.
12689  *
12690  * @assembly: The assembly for which we want the declarative security flags.
12691  * Return the declarative security flags for the assembly.
12692  */
12693 guint32
12694 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12695 {
12696         guint32 idx = 1; /* there is only one assembly */
12697         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12698         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12699         return mono_declsec_get_flags (assembly->image, idx);
12700 }
12701
12702
12703 /*
12704  * Fill actions for the specific index (which may either be an encoded class token or
12705  * an encoded method token) from the metadata image.
12706  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12707  */
12708 static MonoBoolean
12709 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12710         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12711 {
12712         MonoBoolean result = FALSE;
12713         MonoTableInfo *t;
12714         guint32 cols [MONO_DECL_SECURITY_SIZE];
12715         int index = mono_metadata_declsec_from_index (image, token);
12716         int i;
12717
12718         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12719         for (i = index; i < t->rows; i++) {
12720                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12721
12722                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12723                         return result;
12724
12725                 /* if present only replace (class) permissions with method permissions */
12726                 /* if empty accept either class or method permissions */
12727                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12728                         if (!actions->demand.blob) {
12729                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12730                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12731                                 actions->demand.blob = (char*) (blob + 2);
12732                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12733                                 result = TRUE;
12734                         }
12735                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12736                         if (!actions->noncasdemand.blob) {
12737                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12738                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12739                                 actions->noncasdemand.blob = (char*) (blob + 2);
12740                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12741                                 result = TRUE;
12742                         }
12743                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12744                         if (!actions->demandchoice.blob) {
12745                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12746                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12747                                 actions->demandchoice.blob = (char*) (blob + 2);
12748                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12749                                 result = TRUE;
12750                         }
12751                 }
12752         }
12753
12754         return result;
12755 }
12756
12757 static MonoBoolean
12758 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12759         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12760 {
12761         guint32 idx = mono_metadata_token_index (klass->type_token);
12762         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12763         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12764         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12765 }
12766
12767 static MonoBoolean
12768 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12769         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12770 {
12771         guint32 idx = mono_method_get_index (method);
12772         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12773         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12774         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12775 }
12776
12777 /*
12778  * Collect all actions (that requires to generate code in mini) assigned for
12779  * the specified method.
12780  * Note: Don't use the content of actions if the function return FALSE.
12781  */
12782 MonoBoolean
12783 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12784 {
12785         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12786                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12787         MonoBoolean result = FALSE;
12788         guint32 flags;
12789
12790         /* quick exit if no declarative security is present in the metadata */
12791         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12792                 return FALSE;
12793
12794         /* we want the original as the wrapper is "free" of the security informations */
12795         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12796                 method = mono_marshal_method_from_wrapper (method);
12797                 if (!method)
12798                         return FALSE;
12799         }
12800
12801         /* First we look for method-level attributes */
12802         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12803                 mono_class_init (method->klass);
12804                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12805
12806                 result = mono_declsec_get_method_demands_params (method, demands, 
12807                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12808         }
12809
12810         /* Here we use (or create) the class declarative cache to look for demands */
12811         flags = mono_declsec_flags_from_class (method->klass);
12812         if (flags & mask) {
12813                 if (!result) {
12814                         mono_class_init (method->klass);
12815                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12816                 }
12817                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12818                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12819         }
12820
12821         /* The boolean return value is used as a shortcut in case nothing needs to
12822            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12823         return result;
12824 }
12825
12826
12827 /*
12828  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12829  *
12830  * Note: Don't use the content of actions if the function return FALSE.
12831  */
12832 MonoBoolean
12833 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12834 {
12835         MonoBoolean result = FALSE;
12836         guint32 flags;
12837
12838         /* quick exit if no declarative security is present in the metadata */
12839         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12840                 return FALSE;
12841
12842         /* we want the original as the wrapper is "free" of the security informations */
12843         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12844                 method = mono_marshal_method_from_wrapper (method);
12845                 if (!method)
12846                         return FALSE;
12847         }
12848
12849         /* results are independant - zeroize both */
12850         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12851         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12852
12853         /* First we look for method-level attributes */
12854         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12855                 mono_class_init (method->klass);
12856
12857                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12858                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12859         }
12860
12861         /* Here we use (or create) the class declarative cache to look for demands */
12862         flags = mono_declsec_flags_from_class (method->klass);
12863         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12864                 mono_class_init (method->klass);
12865
12866                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12867                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12868         }
12869
12870         return result;
12871 }
12872
12873 /*
12874  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12875  *
12876  * @klass       The inherited class - this is the class that provides the security check (attributes)
12877  * @demans      
12878  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12879  * 
12880  * Note: Don't use the content of actions if the function return FALSE.
12881  */
12882 MonoBoolean
12883 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12884 {
12885         MonoBoolean result = FALSE;
12886         guint32 flags;
12887
12888         /* quick exit if no declarative security is present in the metadata */
12889         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12890                 return FALSE;
12891
12892         /* Here we use (or create) the class declarative cache to look for demands */
12893         flags = mono_declsec_flags_from_class (klass);
12894         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12895                 mono_class_init (klass);
12896                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12897
12898                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12899                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12900         }
12901
12902         return result;
12903 }
12904
12905 /*
12906  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12907  *
12908  * Note: Don't use the content of actions if the function return FALSE.
12909  */
12910 MonoBoolean
12911 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12912 {
12913         /* quick exit if no declarative security is present in the metadata */
12914         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12915                 return FALSE;
12916
12917         /* we want the original as the wrapper is "free" of the security informations */
12918         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12919                 method = mono_marshal_method_from_wrapper (method);
12920                 if (!method)
12921                         return FALSE;
12922         }
12923
12924         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12925                 mono_class_init (method->klass);
12926                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12927
12928                 return mono_declsec_get_method_demands_params (method, demands, 
12929                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12930         }
12931         return FALSE;
12932 }
12933
12934
12935 static MonoBoolean
12936 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12937 {
12938         guint32 cols [MONO_DECL_SECURITY_SIZE];
12939         MonoTableInfo *t;
12940         int i;
12941
12942         int index = mono_metadata_declsec_from_index (image, token);
12943         if (index == -1)
12944                 return FALSE;
12945
12946         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12947         for (i = index; i < t->rows; i++) {
12948                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12949
12950                 /* shortcut - index are ordered */
12951                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12952                         return FALSE;
12953
12954                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12955                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12956                         entry->blob = (char*) (metadata + 2);
12957                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12958                         return TRUE;
12959                 }
12960         }
12961
12962         return FALSE;
12963 }
12964
12965 MonoBoolean
12966 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12967 {
12968         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12969                 guint32 idx = mono_method_get_index (method);
12970                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12971                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12972                 return get_declsec_action (method->klass->image, idx, action, entry);
12973         }
12974         return FALSE;
12975 }
12976
12977 MonoBoolean
12978 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12979 {
12980         /* use cache */
12981         guint32 flags = mono_declsec_flags_from_class (klass);
12982         if (declsec_flags_map [action] & flags) {
12983                 guint32 idx = mono_metadata_token_index (klass->type_token);
12984                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12985                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12986                 return get_declsec_action (klass->image, idx, action, entry);
12987         }
12988         return FALSE;
12989 }
12990
12991 MonoBoolean
12992 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12993 {
12994         guint32 idx = 1; /* there is only one assembly */
12995         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12996         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12997
12998         return get_declsec_action (assembly->image, idx, action, entry);
12999 }
13000
13001 gboolean
13002 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13003 {
13004         MonoObject *res, *exc;
13005         void *params [1];
13006         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
13007         static MonoMethod *method = NULL;
13008
13009         if (!System_Reflection_Emit_TypeBuilder) {
13010                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13011                 g_assert (System_Reflection_Emit_TypeBuilder);
13012         }
13013         if (method == NULL) {
13014                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13015                 g_assert (method);
13016         }
13017
13018         /* 
13019          * The result of mono_type_get_object () might be a System.MonoType but we
13020          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13021          */
13022         g_assert (mono_class_get_ref_info (klass));
13023         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13024
13025         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
13026
13027         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13028         if (exc)
13029                 return FALSE;
13030         else
13031                 return *(MonoBoolean*)mono_object_unbox (res);
13032 }
13033
13034 /**
13035  * mono_reflection_type_get_type:
13036  * @reftype: the System.Type object
13037  *
13038  * Returns the MonoType* associated with the C# System.Type object @reftype.
13039  */
13040 MonoType*
13041 mono_reflection_type_get_type (MonoReflectionType *reftype)
13042 {
13043         g_assert (reftype);
13044
13045         return mono_reflection_type_get_handle (reftype);
13046 }
13047
13048 /**
13049  * mono_reflection_assembly_get_assembly:
13050  * @refassembly: the System.Reflection.Assembly object
13051  *
13052  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13053  */
13054 MonoAssembly*
13055 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13056 {
13057         g_assert (refassembly);
13058
13059         return refassembly->assembly;
13060 }
13061