Merge pull request #1899 from saper/resgencond
[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;
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                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7500                         *p++ = 0;
7501                         break;
7502                 case '*':
7503                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7504                         *p++ = 0;
7505                         break;
7506                 case '[':
7507                         //Decide if it's an array of a generic argument list
7508                         *p++ = 0;
7509
7510                         if (!*p) //XXX test
7511                                 return 0;
7512                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7513                                 rank = 1;
7514                                 while (*p) {
7515                                         if (*p == ']')
7516                                                 break;
7517                                         if (*p == ',')
7518                                                 rank++;
7519                                         else if (*p == '*') /* '*' means unknown lower bound */
7520                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7521                                         else
7522                                                 return 0;
7523                                         ++p;
7524                                 }
7525                                 if (*p++ != ']')
7526                                         return 0;
7527                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7528                         } else {
7529                                 if (rank) /* generic args after array spec*/ //XXX test
7530                                         return 0;
7531                                 info->type_arguments = g_ptr_array_new ();
7532                                 while (*p) {
7533                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7534                                         gboolean fqname = FALSE;
7535
7536                                         g_ptr_array_add (info->type_arguments, subinfo);
7537
7538                                         while (*p == ' ') p++;
7539                                         if (*p == '[') {
7540                                                 p++;
7541                                                 fqname = TRUE;
7542                                         }
7543
7544                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7545                                                 return 0;
7546
7547                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7548                                         if (fqname && (*p != ']')) {
7549                                                 char *aname;
7550
7551                                                 if (*p != ',')
7552                                                         return 0;
7553                                                 *p++ = 0;
7554
7555                                                 aname = p;
7556                                                 while (*p && (*p != ']'))
7557                                                         p++;
7558
7559                                                 if (*p != ']')
7560                                                         return 0;
7561
7562                                                 *p++ = 0;
7563                                                 while (*aname) {
7564                                                         if (g_ascii_isspace (*aname)) {
7565                                                                 ++aname;
7566                                                                 continue;
7567                                                         }
7568                                                         break;
7569                                                 }
7570                                                 if (!*aname ||
7571                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
7572                                                         return 0;
7573                                         } else if (fqname && (*p == ']')) {
7574                                                 *p++ = 0;
7575                                         }
7576                                         if (*p == ']') {
7577                                                 *p++ = 0;
7578                                                 break;
7579                                         } else if (!*p) {
7580                                                 return 0;
7581                                         }
7582                                         *p++ = 0;
7583                                 }
7584                         }
7585                         break;
7586                 case ']':
7587                         if (is_recursed)
7588                                 goto end;
7589                         return 0;
7590                 case ',':
7591                         if (is_recursed)
7592                                 goto end;
7593                         *p++ = 0;
7594                         while (*p) {
7595                                 if (g_ascii_isspace (*p)) {
7596                                         ++p;
7597                                         continue;
7598                                 }
7599                                 break;
7600                         }
7601                         if (!*p)
7602                                 return 0; /* missing assembly name */
7603                         if (!assembly_name_to_aname (&info->assembly, p))
7604                                 return 0;
7605                         break;
7606                 default:
7607                         return 0;
7608                 }
7609                 if (info->assembly.name)
7610                         break;
7611         }
7612         // *w = 0; /* terminate class name */
7613  end:
7614         if (!info->name || !*info->name)
7615                 return 0;
7616         if (endptr)
7617                 *endptr = p;
7618         /* add other consistency checks */
7619         return 1;
7620 }
7621
7622 int
7623 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7624 {
7625         return _mono_reflection_parse_type (name, NULL, FALSE, info);
7626 }
7627
7628 static MonoType*
7629 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7630 {
7631         gboolean type_resolve = FALSE;
7632         MonoType *type;
7633         MonoImage *rootimage = image;
7634
7635         if (info->assembly.name) {
7636                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7637                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7638                         /* 
7639                          * This could happen in the AOT compiler case when the search hook is not
7640                          * installed.
7641                          */
7642                         assembly = image->assembly;
7643                 if (!assembly) {
7644                         /* then we must load the assembly ourselve - see #60439 */
7645                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
7646                         if (!assembly)
7647                                 return NULL;
7648                 }
7649                 image = assembly->image;
7650         } else if (!image) {
7651                 image = mono_defaults.corlib;
7652         }
7653
7654         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7655         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7656                 image = mono_defaults.corlib;
7657                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7658         }
7659
7660         return type;
7661 }
7662
7663 static MonoType*
7664 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7665 {
7666         MonoClass *klass;
7667         GList *mod;
7668         int modval;
7669         gboolean bounded = FALSE;
7670         
7671         if (!image)
7672                 image = mono_defaults.corlib;
7673
7674         if (!rootimage)
7675                 rootimage = mono_defaults.corlib;
7676
7677         if (ignorecase) {
7678                 MonoError error;
7679                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, &error);
7680                 g_assert (mono_error_ok (&error)); /* FIXME Don't swallow the error */
7681         } else {
7682                 klass = mono_class_from_name (image, info->name_space, info->name);
7683         }
7684         if (!klass)
7685                 return NULL;
7686         for (mod = info->nested; mod; mod = mod->next) {
7687                 gpointer iter = NULL;
7688                 MonoClass *parent;
7689
7690                 parent = klass;
7691                 mono_class_init (parent);
7692
7693                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7694                         char *lastp;
7695                         char *nested_name, *nested_nspace;
7696                         gboolean match = TRUE;
7697
7698                         lastp = strrchr (mod->data, '.');
7699                         if (lastp) {
7700                                 /* Nested classes can have namespaces */
7701                                 int nspace_len;
7702
7703                                 nested_name = g_strdup (lastp + 1);
7704                                 nspace_len = lastp - (char*)mod->data;
7705                                 nested_nspace = g_malloc (nspace_len + 1);
7706                                 memcpy (nested_nspace, mod->data, nspace_len);
7707                                 nested_nspace [nspace_len] = '\0';
7708
7709                         } else {
7710                                 nested_name = mod->data;
7711                                 nested_nspace = NULL;
7712                         }
7713
7714                         if (nested_nspace) {
7715                                 if (ignorecase) {
7716                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
7717                                                 match = FALSE;
7718                                 } else {
7719                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
7720                                                 match = FALSE;
7721                                 }
7722                         }
7723                         if (match) {
7724                                 if (ignorecase) {
7725                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
7726                                                 match = FALSE;
7727                                 } else {
7728                                         if (strcmp (klass->name, nested_name) != 0)
7729                                                 match = FALSE;
7730                                 }
7731                         }
7732                         if (lastp) {
7733                                 g_free (nested_name);
7734                                 g_free (nested_nspace);
7735                         }
7736                         if (match)
7737                                 break;
7738                 }
7739
7740                 if (!klass)
7741                         break;
7742         }
7743         if (!klass)
7744                 return NULL;
7745
7746         if (info->type_arguments) {
7747                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7748                 MonoReflectionType *the_type;
7749                 MonoType *instance;
7750                 int i;
7751
7752                 for (i = 0; i < info->type_arguments->len; i++) {
7753                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7754
7755                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7756                         if (!type_args [i]) {
7757                                 g_free (type_args);
7758                                 return NULL;
7759                         }
7760                 }
7761
7762                 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7763
7764                 instance = mono_reflection_bind_generic_parameters (
7765                         the_type, info->type_arguments->len, type_args);
7766
7767                 g_free (type_args);
7768                 if (!instance)
7769                         return NULL;
7770
7771                 klass = mono_class_from_mono_type (instance);
7772         }
7773
7774         for (mod = info->modifiers; mod; mod = mod->next) {
7775                 modval = GPOINTER_TO_UINT (mod->data);
7776                 if (!modval) { /* byref: must be last modifier */
7777                         return &klass->this_arg;
7778                 } else if (modval == -1) {
7779                         klass = mono_ptr_class_get (&klass->byval_arg);
7780                 } else if (modval == -2) {
7781                         bounded = TRUE;
7782                 } else { /* array rank */
7783                         klass = mono_bounded_array_class_get (klass, modval, bounded);
7784                 }
7785         }
7786
7787         return &klass->byval_arg;
7788 }
7789
7790 /*
7791  * mono_reflection_get_type:
7792  * @image: a metadata context
7793  * @info: type description structure
7794  * @ignorecase: flag for case-insensitive string compares
7795  * @type_resolve: whenever type resolve was already tried
7796  *
7797  * Build a MonoType from the type description in @info.
7798  * 
7799  */
7800
7801 MonoType*
7802 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7803         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7804 }
7805
7806 static MonoType*
7807 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7808 {
7809         MonoReflectionAssemblyBuilder *abuilder;
7810         MonoType *type;
7811         int i;
7812
7813         g_assert (assembly_is_dynamic (assembly));
7814         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7815
7816         /* Enumerate all modules */
7817
7818         type = NULL;
7819         if (abuilder->modules) {
7820                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7821                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7822                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7823                         if (type)
7824                                 break;
7825                 }
7826         }
7827
7828         if (!type && abuilder->loaded_modules) {
7829                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7830                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7831                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7832                         if (type)
7833                                 break;
7834                 }
7835         }
7836
7837         return type;
7838 }
7839         
7840 MonoType*
7841 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7842 {
7843         MonoType *type;
7844         MonoReflectionAssembly *assembly;
7845         GString *fullName;
7846         GList *mod;
7847
7848         if (image && image_is_dynamic (image))
7849                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7850         else
7851                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7852         if (type)
7853                 return type;
7854         if (!mono_domain_has_type_resolve (mono_domain_get ()))
7855                 return NULL;
7856
7857         if (type_resolve) {
7858                 if (*type_resolve) 
7859                         return NULL;
7860                 else
7861                         *type_resolve = TRUE;
7862         }
7863         
7864         /* Reconstruct the type name */
7865         fullName = g_string_new ("");
7866         if (info->name_space && (info->name_space [0] != '\0'))
7867                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7868         else
7869                 g_string_printf (fullName, "%s", info->name);
7870         for (mod = info->nested; mod; mod = mod->next)
7871                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7872
7873         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7874         if (assembly) {
7875                 if (assembly_is_dynamic (assembly->assembly))
7876                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7877                 else
7878                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
7879                                                                                                           info, ignorecase);
7880         }
7881         g_string_free (fullName, TRUE);
7882         return type;
7883 }
7884
7885 void
7886 mono_reflection_free_type_info (MonoTypeNameParse *info)
7887 {
7888         g_list_free (info->modifiers);
7889         g_list_free (info->nested);
7890
7891         if (info->type_arguments) {
7892                 int i;
7893
7894                 for (i = 0; i < info->type_arguments->len; i++) {
7895                         MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7896
7897                         mono_reflection_free_type_info (subinfo);
7898                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7899                         g_free (subinfo);
7900                 }
7901
7902                 g_ptr_array_free (info->type_arguments, TRUE);
7903         }
7904 }
7905
7906 /*
7907  * mono_reflection_type_from_name:
7908  * @name: type name.
7909  * @image: a metadata context (can be NULL).
7910  *
7911  * Retrieves a MonoType from its @name. If the name is not fully qualified,
7912  * it defaults to get the type from @image or, if @image is NULL or loading
7913  * from it fails, uses corlib.
7914  * 
7915  */
7916 MonoType*
7917 mono_reflection_type_from_name (char *name, MonoImage *image)
7918 {
7919         MonoType *type = NULL;
7920         MonoTypeNameParse info;
7921         char *tmp;
7922
7923         /* Make a copy since parse_type modifies its argument */
7924         tmp = g_strdup (name);
7925         
7926         /*g_print ("requested type %s\n", str);*/
7927         if (mono_reflection_parse_type (tmp, &info)) {
7928                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7929         }
7930
7931         g_free (tmp);
7932         mono_reflection_free_type_info (&info);
7933         return type;
7934 }
7935
7936 /*
7937  * mono_reflection_get_token:
7938  *
7939  *   Return the metadata token of OBJ which should be an object
7940  * representing a metadata element.
7941  */
7942 guint32
7943 mono_reflection_get_token (MonoObject *obj)
7944 {
7945         MonoClass *klass;
7946         guint32 token = 0;
7947
7948         klass = obj->vtable->klass;
7949
7950         if (strcmp (klass->name, "MethodBuilder") == 0) {
7951                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7952
7953                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7954         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7955                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7956
7957                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7958         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7959                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7960
7961                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7962         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7963                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7964                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7965         } else if (strcmp (klass->name, "MonoType") == 0) {
7966                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7967                 MonoClass *mc = mono_class_from_mono_type (type);
7968                 if (!mono_class_init (mc))
7969                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
7970
7971                 token = mc->type_token;
7972         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7973                    strcmp (klass->name, "MonoMethod") == 0 ||
7974                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
7975                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
7976                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7977                 if (m->method->is_inflated) {
7978                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7979                         return inflated->declaring->token;
7980                 } else {
7981                         token = m->method->token;
7982                 }
7983         } else if (strcmp (klass->name, "MonoField") == 0) {
7984                 MonoReflectionField *f = (MonoReflectionField*)obj;
7985
7986                 if (is_field_on_inst (f->field)) {
7987                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7988
7989                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
7990                                 int field_index = f->field - dgclass->fields;
7991                                 MonoObject *obj;
7992
7993                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7994                                 obj = dgclass->field_objects [field_index];
7995                                 return mono_reflection_get_token (obj);
7996                         }
7997                 }
7998                 token = mono_class_get_field_token (f->field);
7999         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8000                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8001
8002                 token = mono_class_get_property_token (p->property);
8003         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8004                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8005
8006                 token = mono_class_get_event_token (p->event);
8007         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8008                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8009                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8010                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8011
8012                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8013         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8014                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8015
8016                 token = m->token;
8017         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8018                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8019         } else {
8020                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8021                 MonoException *ex = mono_get_exception_not_implemented (msg);
8022                 g_free (msg);
8023                 mono_raise_exception (ex);
8024         }
8025
8026         return token;
8027 }
8028
8029 static MonoClass*
8030 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8031 {
8032         char *n;
8033         MonoType *t;
8034         int slen = mono_metadata_decode_value (p, &p);
8035
8036         mono_error_init (error);
8037
8038         n = g_memdup (p, slen + 1);
8039         n [slen] = 0;
8040         t = mono_reflection_type_from_name (n, image);
8041         if (!t) {
8042                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8043                 /* We don't free n, it's consumed by mono_error */
8044                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8045                 return NULL;
8046         }
8047         g_free (n);
8048         p += slen;
8049         *end = p;
8050         return mono_class_from_mono_type (t);
8051 }
8052
8053 static void*
8054 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8055 {
8056         int slen, type = t->type;
8057         MonoClass *tklass = t->data.klass;
8058
8059         mono_error_init (error);
8060
8061 handle_enum:
8062         switch (type) {
8063         case MONO_TYPE_U1:
8064         case MONO_TYPE_I1:
8065         case MONO_TYPE_BOOLEAN: {
8066                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
8067                 *bval = *p;
8068                 *end = p + 1;
8069                 return bval;
8070         }
8071         case MONO_TYPE_CHAR:
8072         case MONO_TYPE_U2:
8073         case MONO_TYPE_I2: {
8074                 guint16 *val = g_malloc (sizeof (guint16));
8075                 *val = read16 (p);
8076                 *end = p + 2;
8077                 return val;
8078         }
8079 #if SIZEOF_VOID_P == 4
8080         case MONO_TYPE_U:
8081         case MONO_TYPE_I:
8082 #endif
8083         case MONO_TYPE_R4:
8084         case MONO_TYPE_U4:
8085         case MONO_TYPE_I4: {
8086                 guint32 *val = g_malloc (sizeof (guint32));
8087                 *val = read32 (p);
8088                 *end = p + 4;
8089                 return val;
8090         }
8091 #if SIZEOF_VOID_P == 8
8092         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8093         case MONO_TYPE_I:
8094 #endif
8095         case MONO_TYPE_U8:
8096         case MONO_TYPE_I8: {
8097                 guint64 *val = g_malloc (sizeof (guint64));
8098                 *val = read64 (p);
8099                 *end = p + 8;
8100                 return val;
8101         }
8102         case MONO_TYPE_R8: {
8103                 double *val = g_malloc (sizeof (double));
8104                 readr8 (p, val);
8105                 *end = p + 8;
8106                 return val;
8107         }
8108         case MONO_TYPE_VALUETYPE:
8109                 if (t->data.klass->enumtype) {
8110                         type = mono_class_enum_basetype (t->data.klass)->type;
8111                         goto handle_enum;
8112                 } else {
8113                         MonoClass *k =  t->data.klass;
8114                         
8115                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8116                                 guint64 *val = g_malloc (sizeof (guint64));
8117                                 *val = read64 (p);
8118                                 *end = p + 8;
8119                                 return val;
8120                         }
8121                 }
8122                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8123                 break;
8124                 
8125         case MONO_TYPE_STRING:
8126                 if (*p == (char)0xFF) {
8127                         *end = p + 1;
8128                         return NULL;
8129                 }
8130                 slen = mono_metadata_decode_value (p, &p);
8131                 *end = p + slen;
8132                 return mono_string_new_len (mono_domain_get (), p, slen);
8133         case MONO_TYPE_CLASS: {
8134                 char *n;
8135                 MonoType *t;
8136                 if (*p == (char)0xFF) {
8137                         *end = p + 1;
8138                         return NULL;
8139                 }
8140 handle_type:
8141                 slen = mono_metadata_decode_value (p, &p);
8142                 n = g_memdup (p, slen + 1);
8143                 n [slen] = 0;
8144                 t = mono_reflection_type_from_name (n, image);
8145                 if (!t) {
8146                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8147                         /* We don't free n, it's consumed by mono_error */
8148                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8149                         return NULL;
8150                 }
8151                 g_free (n);
8152                 *end = p + slen;
8153                 return mono_type_get_object (mono_domain_get (), t);
8154         }
8155         case MONO_TYPE_OBJECT: {
8156                 char subt = *p++;
8157                 MonoObject *obj;
8158                 MonoClass *subc = NULL;
8159                 void *val;
8160
8161                 if (subt == 0x50) {
8162                         goto handle_type;
8163                 } else if (subt == 0x0E) {
8164                         type = MONO_TYPE_STRING;
8165                         goto handle_enum;
8166                 } else if (subt == 0x1D) {
8167                         MonoType simple_type = {{0}};
8168                         int etype = *p;
8169                         p ++;
8170
8171                         type = MONO_TYPE_SZARRAY;
8172                         if (etype == 0x50) {
8173                                 tklass = mono_defaults.systemtype_class;
8174                         } else if (etype == 0x55) {
8175                                 tklass = load_cattr_enum_type (image, p, &p, error);
8176                                 if (!mono_error_ok (error))
8177                                         return NULL;
8178                         } else {
8179                                 if (etype == 0x51)
8180                                         /* See Partition II, Appendix B3 */
8181                                         etype = MONO_TYPE_OBJECT;
8182                                 simple_type.type = etype;
8183                                 tklass = mono_class_from_mono_type (&simple_type);
8184                         }
8185                         goto handle_enum;
8186                 } else if (subt == 0x55) {
8187                         char *n;
8188                         MonoType *t;
8189                         slen = mono_metadata_decode_value (p, &p);
8190                         n = g_memdup (p, slen + 1);
8191                         n [slen] = 0;
8192                         t = mono_reflection_type_from_name (n, image);
8193                         if (!t) {
8194                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8195                                 /* We don't free n, it's consumed by mono_error */
8196                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8197                                 return NULL;
8198                         }
8199                         g_free (n);
8200                         p += slen;
8201                         subc = mono_class_from_mono_type (t);
8202                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8203                         MonoType simple_type = {{0}};
8204                         simple_type.type = subt;
8205                         subc = mono_class_from_mono_type (&simple_type);
8206                 } else {
8207                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8208                 }
8209                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8210                 obj = NULL;
8211                 if (mono_error_ok (error)) {
8212                         obj = mono_object_new (mono_domain_get (), subc);
8213                         g_assert (!subc->has_references);
8214                         mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8215                 }
8216
8217                 g_free (val);
8218                 return obj;
8219         }
8220         case MONO_TYPE_SZARRAY: {
8221                 MonoArray *arr;
8222                 guint32 i, alen, basetype;
8223                 alen = read32 (p);
8224                 p += 4;
8225                 if (alen == 0xffffffff) {
8226                         *end = p;
8227                         return NULL;
8228                 }
8229                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8230                 basetype = tklass->byval_arg.type;
8231                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8232                         basetype = mono_class_enum_basetype (tklass)->type;
8233                 switch (basetype)
8234                 {
8235                         case MONO_TYPE_U1:
8236                         case MONO_TYPE_I1:
8237                         case MONO_TYPE_BOOLEAN:
8238                                 for (i = 0; i < alen; i++) {
8239                                         MonoBoolean val = *p++;
8240                                         mono_array_set (arr, MonoBoolean, i, val);
8241                                 }
8242                                 break;
8243                         case MONO_TYPE_CHAR:
8244                         case MONO_TYPE_U2:
8245                         case MONO_TYPE_I2:
8246                                 for (i = 0; i < alen; i++) {
8247                                         guint16 val = read16 (p);
8248                                         mono_array_set (arr, guint16, i, val);
8249                                         p += 2;
8250                                 }
8251                                 break;
8252                         case MONO_TYPE_R4:
8253                         case MONO_TYPE_U4:
8254                         case MONO_TYPE_I4:
8255                                 for (i = 0; i < alen; i++) {
8256                                         guint32 val = read32 (p);
8257                                         mono_array_set (arr, guint32, i, val);
8258                                         p += 4;
8259                                 }
8260                                 break;
8261                         case MONO_TYPE_R8:
8262                                 for (i = 0; i < alen; i++) {
8263                                         double val;
8264                                         readr8 (p, &val);
8265                                         mono_array_set (arr, double, i, val);
8266                                         p += 8;
8267                                 }
8268                                 break;
8269                         case MONO_TYPE_U8:
8270                         case MONO_TYPE_I8:
8271                                 for (i = 0; i < alen; i++) {
8272                                         guint64 val = read64 (p);
8273                                         mono_array_set (arr, guint64, i, val);
8274                                         p += 8;
8275                                 }
8276                                 break;
8277                         case MONO_TYPE_CLASS:
8278                         case MONO_TYPE_OBJECT:
8279                         case MONO_TYPE_STRING:
8280                         case MONO_TYPE_SZARRAY:
8281                                 for (i = 0; i < alen; i++) {
8282                                         MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8283                                         if (!mono_error_ok (error))
8284                                                 return NULL;
8285                                         mono_array_setref (arr, i, item);
8286                                 }
8287                                 break;
8288                         default:
8289                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8290                 }
8291                 *end=p;
8292                 return arr;
8293         }
8294         default:
8295                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8296         }
8297         return NULL;
8298 }
8299
8300 static MonoObject*
8301 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8302 {
8303         static MonoClass *klass;
8304         static MonoMethod *ctor;
8305         MonoObject *retval;
8306         void *params [2], *unboxed;
8307
8308         if (!klass)
8309                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8310         if (!ctor)
8311                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8312         
8313         params [0] = mono_type_get_object (mono_domain_get (), t);
8314         params [1] = val;
8315         retval = mono_object_new (mono_domain_get (), klass);
8316         unboxed = mono_object_unbox (retval);
8317         mono_runtime_invoke (ctor, unboxed, params, NULL);
8318
8319         return retval;
8320 }
8321
8322 static MonoObject*
8323 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8324 {
8325         static MonoClass *klass;
8326         static MonoMethod *ctor;
8327         MonoObject *retval;
8328         void *unboxed, *params [2];
8329
8330         if (!klass)
8331                 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8332         if (!ctor)
8333                 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8334
8335         params [0] = minfo;
8336         params [1] = typedarg;
8337         retval = mono_object_new (mono_domain_get (), klass);
8338         unboxed = mono_object_unbox (retval);
8339         mono_runtime_invoke (ctor, unboxed, params, NULL);
8340
8341         return retval;
8342 }
8343
8344 static gboolean
8345 type_is_reference (MonoType *type)
8346 {
8347         switch (type->type) {
8348         case MONO_TYPE_BOOLEAN:
8349         case MONO_TYPE_CHAR:
8350         case MONO_TYPE_U:
8351         case MONO_TYPE_I:
8352         case MONO_TYPE_U1:
8353         case MONO_TYPE_I1:
8354         case MONO_TYPE_U2:
8355         case MONO_TYPE_I2:
8356         case MONO_TYPE_U4:
8357         case MONO_TYPE_I4:
8358         case MONO_TYPE_U8:
8359         case MONO_TYPE_I8:
8360         case MONO_TYPE_R8:
8361         case MONO_TYPE_R4:
8362         case MONO_TYPE_VALUETYPE:
8363                 return FALSE;
8364         default:
8365                 return TRUE;
8366         }
8367 }
8368
8369 static void
8370 free_param_data (MonoMethodSignature *sig, void **params) {
8371         int i;
8372         for (i = 0; i < sig->param_count; ++i) {
8373                 if (!type_is_reference (sig->params [i]))
8374                         g_free (params [i]);
8375         }
8376 }
8377
8378 /*
8379  * Find the field index in the metadata FieldDef table.
8380  */
8381 static guint32
8382 find_field_index (MonoClass *klass, MonoClassField *field) {
8383         int i;
8384
8385         for (i = 0; i < klass->field.count; ++i) {
8386                 if (field == &klass->fields [i])
8387                         return klass->field.first + 1 + i;
8388         }
8389         return 0;
8390 }
8391
8392 /*
8393  * Find the property index in the metadata Property table.
8394  */
8395 static guint32
8396 find_property_index (MonoClass *klass, MonoProperty *property) {
8397         int i;
8398
8399         for (i = 0; i < klass->ext->property.count; ++i) {
8400                 if (property == &klass->ext->properties [i])
8401                         return klass->ext->property.first + 1 + i;
8402         }
8403         return 0;
8404 }
8405
8406 /*
8407  * Find the event index in the metadata Event table.
8408  */
8409 static guint32
8410 find_event_index (MonoClass *klass, MonoEvent *event) {
8411         int i;
8412
8413         for (i = 0; i < klass->ext->event.count; ++i) {
8414                 if (event == &klass->ext->events [i])
8415                         return klass->ext->event.first + 1 + i;
8416         }
8417         return 0;
8418 }
8419
8420 static MonoObject*
8421 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8422 {
8423         const char *p = (const char*)data;
8424         const char *named;
8425         guint32 i, j, num_named;
8426         MonoObject *attr;
8427         void *params_buf [32];
8428         void **params = NULL;
8429         MonoMethodSignature *sig;
8430         MonoObject *exc = NULL;
8431
8432         mono_error_init (error);
8433
8434         mono_class_init (method->klass);
8435
8436         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8437                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8438                 return NULL;
8439         }
8440
8441         if (len == 0) {
8442                 attr = mono_object_new (mono_domain_get (), method->klass);
8443                 mono_runtime_invoke (method, attr, NULL, NULL);
8444                 return attr;
8445         }
8446
8447         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8448                 return NULL;
8449
8450         /*g_print ("got attr %s\n", method->klass->name);*/
8451
8452         sig = mono_method_signature (method);
8453         if (sig->param_count < 32) {
8454                 params = params_buf;
8455                 memset (params, 0, sizeof (void*) * sig->param_count);
8456         } else {
8457                 /* Allocate using GC so it gets GC tracking */
8458                 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
8459         }
8460
8461         /* skip prolog */
8462         p += 2;
8463         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8464                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8465                 if (!mono_error_ok (error))
8466                         goto fail;
8467         }
8468
8469         named = p;
8470         attr = mono_object_new (mono_domain_get (), method->klass);
8471
8472         mono_runtime_invoke (method, attr, params, &exc);
8473         if (exc)
8474                 goto fail;
8475         num_named = read16 (named);
8476         named += 2;
8477         for (j = 0; j < num_named; j++) {
8478                 gint name_len;
8479                 char *name, named_type, data_type;
8480                 named_type = *named++;
8481                 data_type = *named++; /* type of data */
8482                 if (data_type == MONO_TYPE_SZARRAY)
8483                         data_type = *named++;
8484                 if (data_type == MONO_TYPE_ENUM) {
8485                         gint type_len;
8486                         char *type_name;
8487                         type_len = mono_metadata_decode_blob_size (named, &named);
8488                         type_name = g_malloc (type_len + 1);
8489                         memcpy (type_name, named, type_len);
8490                         type_name [type_len] = 0;
8491                         named += type_len;
8492                         /* FIXME: lookup the type and check type consistency */
8493                         g_free (type_name);
8494                 }
8495                 name_len = mono_metadata_decode_blob_size (named, &named);
8496                 name = g_malloc (name_len + 1);
8497                 memcpy (name, named, name_len);
8498                 name [name_len] = 0;
8499                 named += name_len;
8500                 if (named_type == 0x53) {
8501                         MonoClassField *field;
8502                         void *val;
8503
8504                         /* how this fail is a blackbox */
8505                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
8506                         if (!field) {
8507                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
8508                                 g_free (name);
8509                                 goto fail;
8510                         }
8511
8512                         val = load_cattr_value (image, field->type, named, &named, error);
8513                         if (!mono_error_ok (error)) {
8514                                 g_free (name);
8515                                 if (!type_is_reference (field->type))
8516                                         g_free (val);
8517                                 goto fail;
8518                         }
8519
8520                         mono_field_set_value (attr, field, val);
8521                         if (!type_is_reference (field->type))
8522                                 g_free (val);
8523                 } else if (named_type == 0x54) {
8524                         MonoProperty *prop;
8525                         void *pparams [1];
8526                         MonoType *prop_type;
8527
8528                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8529
8530                         if (!prop) {
8531                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
8532                                 g_free (name);
8533                                 goto fail;
8534                         }
8535
8536                         if (!prop->set) {
8537                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
8538                                 g_free (name);
8539                                 goto fail;
8540                         }
8541
8542                         /* can we have more that 1 arg in a custom attr named property? */
8543                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8544                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8545
8546                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
8547                         if (!mono_error_ok (error)) {
8548                                 g_free (name);
8549                                 if (!type_is_reference (prop_type))
8550                                         g_free (pparams [0]);
8551                                 goto fail;
8552                         }
8553
8554
8555                         mono_property_set_value (prop, attr, pparams, NULL);
8556                         if (!type_is_reference (prop_type))
8557                                 g_free (pparams [0]);
8558                 }
8559                 g_free (name);
8560         }
8561
8562         free_param_data (method->signature, params);
8563         if (params != params_buf)
8564                 mono_gc_free_fixed (params);
8565
8566         return attr;
8567
8568 fail:
8569         free_param_data (method->signature, params);
8570         if (params != params_buf)
8571                 mono_gc_free_fixed (params);
8572         if (exc)
8573                 mono_raise_exception ((MonoException*)exc);
8574         return NULL;
8575 }
8576         
8577 /*
8578  * mono_reflection_create_custom_attr_data_args:
8579  *
8580  *   Create an array of typed and named arguments from the cattr blob given by DATA.
8581  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8582  * NAMED_ARG_INFO will contain information about the named arguments.
8583  */
8584 void
8585 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)
8586 {
8587         MonoArray *typedargs, *namedargs;
8588         MonoClass *attrklass;
8589         MonoDomain *domain;
8590         const char *p = (const char*)data;
8591         const char *named;
8592         guint32 i, j, num_named;
8593         CattrNamedArg *arginfo = NULL;
8594
8595         *typed_args = NULL;
8596         *named_args = NULL;
8597         *named_arg_info = NULL;
8598
8599         mono_error_init (error);
8600
8601         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8602                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8603                 return;
8604         }
8605
8606         mono_class_init (method->klass);
8607         
8608         domain = mono_domain_get ();
8609
8610         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8611                 return;
8612
8613         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8614         
8615         /* skip prolog */
8616         p += 2;
8617         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8618                 MonoObject *obj;
8619                 void *val;
8620
8621                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
8622                 if (!mono_error_ok (error)) {
8623                         if (!type_is_reference (mono_method_signature (method)->params [i]))
8624                                 g_free (val);
8625                         return;
8626                 }
8627
8628                 obj = type_is_reference (mono_method_signature (method)->params [i]) ? 
8629                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8630                 mono_array_setref (typedargs, i, obj);
8631
8632                 if (!type_is_reference (mono_method_signature (method)->params [i]))
8633                         g_free (val);
8634         }
8635
8636         named = p;
8637         num_named = read16 (named);
8638         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8639         named += 2;
8640         attrklass = method->klass;
8641
8642         arginfo = g_new0 (CattrNamedArg, num_named);
8643         *named_arg_info = arginfo;
8644
8645         for (j = 0; j < num_named; j++) {
8646                 gint name_len;
8647                 char *name, named_type, data_type;
8648                 named_type = *named++;
8649                 data_type = *named++; /* type of data */
8650                 if (data_type == MONO_TYPE_SZARRAY)
8651                         data_type = *named++;
8652                 if (data_type == MONO_TYPE_ENUM) {
8653                         gint type_len;
8654                         char *type_name;
8655                         type_len = mono_metadata_decode_blob_size (named, &named);
8656                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
8657                                 goto fail;
8658
8659                         type_name = g_malloc (type_len + 1);
8660                         memcpy (type_name, named, type_len);
8661                         type_name [type_len] = 0;
8662                         named += type_len;
8663                         /* FIXME: lookup the type and check type consistency */
8664                         g_free (type_name);
8665                 }
8666                 name_len = mono_metadata_decode_blob_size (named, &named);
8667                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
8668                         goto fail;
8669                 name = g_malloc (name_len + 1);
8670                 memcpy (name, named, name_len);
8671                 name [name_len] = 0;
8672                 named += name_len;
8673                 if (named_type == 0x53) {
8674                         MonoObject *obj;
8675                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8676                         void *val;
8677
8678                         if (!field) {
8679                                 g_free (name);
8680                                 goto fail;
8681                         }
8682
8683                         arginfo [j].type = field->type;
8684                         arginfo [j].field = field;
8685
8686                         val = load_cattr_value (image, field->type, named, &named, error);
8687                         if (!mono_error_ok (error)) {
8688                                 if (!type_is_reference (field->type))
8689                                         g_free (val);
8690                                 g_free (name);
8691                                 return;
8692                         }
8693
8694                         obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8695                         mono_array_setref (namedargs, j, obj);
8696                         if (!type_is_reference (field->type))
8697                                 g_free (val);
8698                 } else if (named_type == 0x54) {
8699                         MonoObject *obj;
8700                         MonoType *prop_type;
8701                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8702                         void *val;
8703
8704                         if (!prop || !prop->set) {
8705                                 g_free (name);
8706                                 goto fail;
8707                         }
8708
8709                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
8710                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8711
8712                         arginfo [j].type = prop_type;
8713                         arginfo [j].prop = prop;
8714
8715                         val = load_cattr_value (image, prop_type, named, &named, error);
8716                         if (!mono_error_ok (error)) {
8717                                 if (!type_is_reference (prop_type))
8718                                         g_free (val);
8719                                 g_free (name);
8720                                 return;
8721                         }
8722
8723                         obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8724                         mono_array_setref (namedargs, j, obj);
8725                         if (!type_is_reference (prop_type))
8726                                 g_free (val);
8727                 }
8728                 g_free (name);
8729         }
8730
8731         *typed_args = typedargs;
8732         *named_args = namedargs;
8733         return;
8734 fail:
8735         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8736         g_free (arginfo);
8737         *named_arg_info = NULL;
8738 }
8739
8740 void
8741 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8742 {
8743         MonoDomain *domain;
8744         MonoArray *typedargs, *namedargs;
8745         MonoImage *image;
8746         MonoMethod *method;
8747         CattrNamedArg *arginfo = NULL;
8748         MonoError error;
8749         int i;
8750
8751         *ctor_args = NULL;
8752         *named_args = NULL;
8753
8754         if (len == 0)
8755                 return;
8756
8757         image = assembly->assembly->image;
8758         method = ref_method->method;
8759         domain = mono_object_domain (ref_method);
8760
8761         if (!mono_class_init (method->klass))
8762                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8763
8764         mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo, &error);
8765         if (!mono_error_ok (&error))
8766                 mono_error_raise_exception (&error);
8767         if (mono_loader_get_last_error ())
8768                 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8769
8770         if (!typedargs || !namedargs) {
8771                 g_free (arginfo);
8772                 return;
8773         }
8774
8775         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8776                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8777                 MonoObject *typedarg;
8778
8779                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8780                 mono_array_setref (typedargs, i, typedarg);
8781         }
8782
8783         for (i = 0; i < mono_array_length (namedargs); ++i) {
8784                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8785                 MonoObject *typedarg, *namedarg, *minfo;
8786
8787                 if (arginfo [i].prop)
8788                         minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8789                 else
8790                         minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8791
8792                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8793                 namedarg = create_cattr_named_arg (minfo, typedarg);
8794
8795                 mono_array_setref (namedargs, i, namedarg);
8796         }
8797
8798         *ctor_args = typedargs;
8799         *named_args = namedargs;
8800         g_free (arginfo);
8801 }
8802
8803 static MonoObject*
8804 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8805 {
8806         static MonoMethod *ctor;
8807         MonoDomain *domain;
8808         MonoObject *attr;
8809         void *params [4];
8810
8811         g_assert (image->assembly);
8812
8813         if (!ctor)
8814                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8815
8816         domain = mono_domain_get ();
8817         attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8818         params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8819         params [1] = mono_assembly_get_object (domain, image->assembly);
8820         params [2] = (gpointer)&cattr->data;
8821         params [3] = &cattr->data_size;
8822         mono_runtime_invoke (ctor, attr, params, NULL);
8823         return attr;
8824 }
8825
8826 static MonoArray*
8827 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8828 {
8829         MonoArray *result;
8830         MonoObject *attr;
8831         int i, n;
8832
8833         mono_error_init (error);
8834
8835         n = 0;
8836         for (i = 0; i < cinfo->num_attrs; ++i) {
8837                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8838                         n ++;
8839         }
8840
8841         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8842         n = 0;
8843         for (i = 0; i < cinfo->num_attrs; ++i) {
8844                 if (!cinfo->attrs [i].ctor)
8845                         /* The cattr type is not finished yet */
8846                         /* We should include the type name but cinfo doesn't contain it */
8847                         mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8848                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8849                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8850                         if (!mono_error_ok (error))
8851                                 return result;
8852                         mono_array_setref (result, n, attr);
8853                         n ++;
8854                 }
8855         }
8856         return result;
8857 }
8858
8859 MonoArray*
8860 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8861 {
8862         MonoError error;
8863         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8864         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
8865
8866         return result;
8867 }
8868
8869 static MonoArray*
8870 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8871 {
8872         MonoArray *result;
8873         MonoObject *attr;
8874         int i;
8875         
8876         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8877         for (i = 0; i < cinfo->num_attrs; ++i) {
8878                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8879                 mono_array_setref (result, i, attr);
8880         }
8881         return result;
8882 }
8883
8884 /**
8885  * mono_custom_attrs_from_index:
8886  *
8887  * Returns: NULL if no attributes are found or if a loading error occurs.
8888  */
8889 MonoCustomAttrInfo*
8890 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8891 {
8892         guint32 mtoken, i, len;
8893         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8894         MonoTableInfo *ca;
8895         MonoCustomAttrInfo *ainfo;
8896         GList *tmp, *list = NULL;
8897         const char *data;
8898         MonoCustomAttrEntry* attr;
8899
8900         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8901
8902         i = mono_metadata_custom_attrs_from_index (image, idx);
8903         if (!i)
8904                 return NULL;
8905         i --;
8906         while (i < ca->rows) {
8907                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8908                         break;
8909                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8910                 ++i;
8911         }
8912         len = g_list_length (list);
8913         if (!len)
8914                 return NULL;
8915         ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8916         ainfo->num_attrs = len;
8917         ainfo->image = image;
8918         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
8919                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8920                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8921                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8922                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8923                         mtoken |= MONO_TOKEN_METHOD_DEF;
8924                         break;
8925                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8926                         mtoken |= MONO_TOKEN_MEMBER_REF;
8927                         break;
8928                 default:
8929                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8930                         break;
8931                 }
8932                 attr = &ainfo->attrs [i - 1];
8933                 attr->ctor = mono_get_method (image, mtoken, NULL);
8934                 if (!attr->ctor) {
8935                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8936                         g_list_free (list);
8937                         g_free (ainfo);
8938                         return NULL;
8939                 }
8940
8941                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8942                         /*FIXME raising an exception here doesn't make any sense*/
8943                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8944                         g_list_free (list);
8945                         g_free (ainfo);
8946                         return NULL;
8947                 }
8948                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8949                 attr->data_size = mono_metadata_decode_value (data, &data);
8950                 attr->data = (guchar*)data;
8951         }
8952         g_list_free (list);
8953
8954         return ainfo;
8955 }
8956
8957 MonoCustomAttrInfo*
8958 mono_custom_attrs_from_method (MonoMethod *method)
8959 {
8960         guint32 idx;
8961
8962         /*
8963          * An instantiated method has the same cattrs as the generic method definition.
8964          *
8965          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8966          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8967          */
8968         if (method->is_inflated)
8969                 method = ((MonoMethodInflated *) method)->declaring;
8970         
8971         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
8972                 return lookup_custom_attr (method->klass->image, method);
8973
8974         if (!method->token)
8975                 /* Synthetic methods */
8976                 return NULL;
8977
8978         idx = mono_method_get_index (method);
8979         idx <<= MONO_CUSTOM_ATTR_BITS;
8980         idx |= MONO_CUSTOM_ATTR_METHODDEF;
8981         return mono_custom_attrs_from_index (method->klass->image, idx);
8982 }
8983
8984 MonoCustomAttrInfo*
8985 mono_custom_attrs_from_class (MonoClass *klass)
8986 {
8987         guint32 idx;
8988
8989         if (klass->generic_class)
8990                 klass = klass->generic_class->container_class;
8991
8992         if (image_is_dynamic (klass->image))
8993                 return lookup_custom_attr (klass->image, klass);
8994
8995         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8996                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8997                 idx <<= MONO_CUSTOM_ATTR_BITS;
8998                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8999         } else {
9000                 idx = mono_metadata_token_index (klass->type_token);
9001                 idx <<= MONO_CUSTOM_ATTR_BITS;
9002                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9003         }
9004         return mono_custom_attrs_from_index (klass->image, idx);
9005 }
9006
9007 MonoCustomAttrInfo*
9008 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9009 {
9010         guint32 idx;
9011         
9012         if (image_is_dynamic (assembly->image))
9013                 return lookup_custom_attr (assembly->image, assembly);
9014         idx = 1; /* there is only one assembly */
9015         idx <<= MONO_CUSTOM_ATTR_BITS;
9016         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9017         return mono_custom_attrs_from_index (assembly->image, idx);
9018 }
9019
9020 static MonoCustomAttrInfo*
9021 mono_custom_attrs_from_module (MonoImage *image)
9022 {
9023         guint32 idx;
9024         
9025         if (image_is_dynamic (image))
9026                 return lookup_custom_attr (image, image);
9027         idx = 1; /* there is only one module */
9028         idx <<= MONO_CUSTOM_ATTR_BITS;
9029         idx |= MONO_CUSTOM_ATTR_MODULE;
9030         return mono_custom_attrs_from_index (image, idx);
9031 }
9032
9033 MonoCustomAttrInfo*
9034 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9035 {
9036         guint32 idx;
9037         
9038         if (image_is_dynamic (klass->image)) {
9039                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9040                 return lookup_custom_attr (klass->image, property);
9041         }
9042         idx = find_property_index (klass, property);
9043         idx <<= MONO_CUSTOM_ATTR_BITS;
9044         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9045         return mono_custom_attrs_from_index (klass->image, idx);
9046 }
9047
9048 MonoCustomAttrInfo*
9049 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9050 {
9051         guint32 idx;
9052         
9053         if (image_is_dynamic (klass->image)) {
9054                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9055                 return lookup_custom_attr (klass->image, event);
9056         }
9057         idx = find_event_index (klass, event);
9058         idx <<= MONO_CUSTOM_ATTR_BITS;
9059         idx |= MONO_CUSTOM_ATTR_EVENT;
9060         return mono_custom_attrs_from_index (klass->image, idx);
9061 }
9062
9063 MonoCustomAttrInfo*
9064 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9065 {
9066         guint32 idx;
9067         if (image_is_dynamic (klass->image)) {
9068                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9069                 return lookup_custom_attr (klass->image, field);
9070         }
9071         idx = find_field_index (klass, field);
9072         idx <<= MONO_CUSTOM_ATTR_BITS;
9073         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9074         return mono_custom_attrs_from_index (klass->image, idx);
9075 }
9076
9077 /**
9078  * mono_custom_attrs_from_param:
9079  * @method: handle to the method that we want to retrieve custom parameter information from
9080  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9081  *
9082  * The result must be released with mono_custom_attrs_free().
9083  *
9084  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9085  */
9086 MonoCustomAttrInfo*
9087 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9088 {
9089         MonoTableInfo *ca;
9090         guint32 i, idx, method_index;
9091         guint32 param_list, param_last, param_pos, found;
9092         MonoImage *image;
9093         MonoReflectionMethodAux *aux;
9094
9095         /*
9096          * An instantiated method has the same cattrs as the generic method definition.
9097          *
9098          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9099          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9100          */
9101         if (method->is_inflated)
9102                 method = ((MonoMethodInflated *) method)->declaring;
9103
9104         if (image_is_dynamic (method->klass->image)) {
9105                 MonoCustomAttrInfo *res, *ainfo;
9106                 int size;
9107
9108                 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9109                 if (!aux || !aux->param_cattr)
9110                         return NULL;
9111
9112                 /* Need to copy since it will be freed later */
9113                 ainfo = aux->param_cattr [param];
9114                 if (!ainfo)
9115                         return NULL;
9116                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9117                 res = g_malloc0 (size);
9118                 memcpy (res, ainfo, size);
9119                 return res;
9120         }
9121
9122         image = method->klass->image;
9123         method_index = mono_method_get_index (method);
9124         if (!method_index)
9125                 return NULL;
9126         ca = &image->tables [MONO_TABLE_METHOD];
9127
9128         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9129         if (method_index == ca->rows) {
9130                 ca = &image->tables [MONO_TABLE_PARAM];
9131                 param_last = ca->rows + 1;
9132         } else {
9133                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9134                 ca = &image->tables [MONO_TABLE_PARAM];
9135         }
9136         found = FALSE;
9137         for (i = param_list; i < param_last; ++i) {
9138                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9139                 if (param_pos == param) {
9140                         found = TRUE;
9141                         break;
9142                 }
9143         }
9144         if (!found)
9145                 return NULL;
9146         idx = i;
9147         idx <<= MONO_CUSTOM_ATTR_BITS;
9148         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9149         return mono_custom_attrs_from_index (image, idx);
9150 }
9151
9152 gboolean
9153 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9154 {
9155         int i;
9156         MonoClass *klass;
9157         for (i = 0; i < ainfo->num_attrs; ++i) {
9158                 klass = ainfo->attrs [i].ctor->klass;
9159                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9160                         return TRUE;
9161         }
9162         return FALSE;
9163 }
9164
9165 MonoObject*
9166 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9167 {
9168         MonoError error;
9169         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9170         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9171         return res;
9172 }
9173
9174 MonoObject*
9175 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9176 {
9177         int i, attr_index;
9178         MonoClass *klass;
9179         MonoArray *attrs;
9180
9181         mono_error_init (error);
9182
9183         attr_index = -1;
9184         for (i = 0; i < ainfo->num_attrs; ++i) {
9185                 klass = ainfo->attrs [i].ctor->klass;
9186                 if (mono_class_has_parent (klass, attr_klass)) {
9187                         attr_index = i;
9188                         break;
9189                 }
9190         }
9191         if (attr_index == -1)
9192                 return NULL;
9193
9194         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9195         if (!mono_error_ok (error))
9196                 return NULL;
9197         return mono_array_get (attrs, MonoObject*, attr_index);
9198 }
9199
9200 /*
9201  * mono_reflection_get_custom_attrs_info:
9202  * @obj: a reflection object handle
9203  *
9204  * Return the custom attribute info for attributes defined for the
9205  * reflection handle @obj. The objects.
9206  *
9207  * FIXME this function leaks like a sieve for SRE objects.
9208  */
9209 MonoCustomAttrInfo*
9210 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9211 {
9212         MonoClass *klass;
9213         MonoCustomAttrInfo *cinfo = NULL;
9214         
9215         klass = obj->vtable->klass;
9216         if (klass == mono_defaults.monotype_class) {
9217                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9218                 klass = mono_class_from_mono_type (type);
9219                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9220                 cinfo = mono_custom_attrs_from_class (klass);
9221         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9222                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9223                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9224         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9225                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9226                 cinfo = mono_custom_attrs_from_module (module->image);
9227         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9228                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9229                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9230         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9231                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9232                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9233         } else if (strcmp ("MonoField", klass->name) == 0) {
9234                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9235                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9236         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9237                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9238                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9239         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9240                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9241                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9242         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9243                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9244                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9245                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9246                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9247                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9248                 } else if (is_sr_mono_property (member_class)) {
9249                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9250                         MonoMethod *method;
9251                         if (!(method = prop->property->get))
9252                                 method = prop->property->set;
9253                         g_assert (method);
9254
9255                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9256                 } 
9257 #ifndef DISABLE_REFLECTION_EMIT
9258                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9259                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
9260                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9261                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9262                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9263                         MonoMethod *method = NULL;
9264                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9265                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9266                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9267                                 method = ((MonoReflectionMethod *)c->cb)->method;
9268                         else
9269                                 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));
9270
9271                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9272                 } 
9273 #endif
9274                 else {
9275                         char *type_name = mono_type_get_full_name (member_class);
9276                         char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
9277                         MonoException *ex = mono_get_exception_not_supported  (msg);
9278                         g_free (type_name);
9279                         g_free (msg);
9280                         mono_raise_exception (ex);
9281                 }
9282         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9283                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9284                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9285         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9286                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9287                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9288         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9289                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9290                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9291         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9292                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9293                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9294         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9295                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9296                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9297         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9298                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9299                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9300         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9301                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9302                 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
9303         } else { /* handle other types here... */
9304                 g_error ("get custom attrs not yet supported for %s", klass->name);
9305         }
9306
9307         return cinfo;
9308 }
9309
9310 /*
9311  * mono_reflection_get_custom_attrs_by_type:
9312  * @obj: a reflection object handle
9313  *
9314  * Return an array with all the custom attributes defined of the
9315  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9316  * of that type are returned. The objects are fully build. Return NULL if a loading error
9317  * occurs.
9318  */
9319 MonoArray*
9320 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9321 {
9322         MonoArray *result;
9323         MonoCustomAttrInfo *cinfo;
9324
9325         mono_error_init (error);
9326
9327         cinfo = mono_reflection_get_custom_attrs_info (obj);
9328         if (cinfo) {
9329                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9330                 if (!cinfo->cached)
9331                         mono_custom_attrs_free (cinfo);
9332         } else {
9333                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9334                 if (mono_loader_get_last_error ())
9335                         return NULL;
9336                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9337         }
9338
9339         return result;
9340 }
9341
9342 /*
9343  * mono_reflection_get_custom_attrs:
9344  * @obj: a reflection object handle
9345  *
9346  * Return an array with all the custom attributes defined of the
9347  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9348  * occurs.
9349  */
9350 MonoArray*
9351 mono_reflection_get_custom_attrs (MonoObject *obj)
9352 {
9353         MonoError error;
9354
9355         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9356 }
9357
9358 /*
9359  * mono_reflection_get_custom_attrs_data:
9360  * @obj: a reflection obj handle
9361  *
9362  * Returns an array of System.Reflection.CustomAttributeData,
9363  * which include information about attributes reflected on
9364  * types loaded using the Reflection Only methods
9365  */
9366 MonoArray*
9367 mono_reflection_get_custom_attrs_data (MonoObject *obj)
9368 {
9369         MonoArray *result;
9370         MonoCustomAttrInfo *cinfo;
9371
9372         cinfo = mono_reflection_get_custom_attrs_info (obj);
9373         if (cinfo) {
9374                 result = mono_custom_attrs_data_construct (cinfo);
9375                 if (!cinfo->cached)
9376                         mono_custom_attrs_free (cinfo);
9377         } else
9378                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
9379
9380         return result;
9381 }
9382
9383 static MonoReflectionType*
9384 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
9385 {
9386         static MonoMethod *method_get_underlying_system_type = NULL;
9387         MonoMethod *usertype_method;
9388
9389         if (!method_get_underlying_system_type)
9390                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
9391         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
9392         return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
9393 }
9394
9395
9396 static gboolean
9397 is_corlib_type (MonoClass *class)
9398 {
9399         return class->image == mono_defaults.corlib;
9400 }
9401
9402 #define check_corlib_type_cached(_class, _namespace, _name) do { \
9403         static MonoClass *cached_class; \
9404         if (cached_class) \
9405                 return cached_class == _class; \
9406         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
9407                 cached_class = _class; \
9408                 return TRUE; \
9409         } \
9410         return FALSE; \
9411 } while (0) \
9412
9413
9414 #ifndef DISABLE_REFLECTION_EMIT
9415 static gboolean
9416 is_sre_array (MonoClass *class)
9417 {
9418         check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
9419 }
9420
9421 static gboolean
9422 is_sre_byref (MonoClass *class)
9423 {
9424         check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
9425 }
9426
9427 static gboolean
9428 is_sre_pointer (MonoClass *class)
9429 {
9430         check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
9431 }
9432
9433 static gboolean
9434 is_sre_generic_instance (MonoClass *class)
9435 {
9436         check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
9437 }
9438
9439 static gboolean
9440 is_sre_type_builder (MonoClass *class)
9441 {
9442         check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
9443 }
9444
9445 static gboolean
9446 is_sre_method_builder (MonoClass *class)
9447 {
9448         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9449 }
9450
9451 static gboolean
9452 is_sre_ctor_builder (MonoClass *class)
9453 {
9454         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9455 }
9456
9457 static gboolean
9458 is_sre_field_builder (MonoClass *class)
9459 {
9460         check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9461 }
9462
9463 static gboolean
9464 is_sre_method_on_tb_inst (MonoClass *class)
9465 {
9466         check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9467 }
9468
9469 static gboolean
9470 is_sre_ctor_on_tb_inst (MonoClass *class)
9471 {
9472         check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9473 }
9474
9475 MonoType*
9476 mono_reflection_type_get_handle (MonoReflectionType* ref)
9477 {
9478         MonoClass *class;
9479         if (!ref)
9480                 return NULL;
9481         if (ref->type)
9482                 return ref->type;
9483
9484         if (is_usertype (ref)) {
9485                 ref = mono_reflection_type_get_underlying_system_type (ref);
9486                 if (ref == NULL || is_usertype (ref))
9487                         return NULL;
9488                 if (ref->type)
9489                         return ref->type;
9490         }
9491
9492         class = mono_object_class (ref);
9493
9494         if (is_sre_array (class)) {
9495                 MonoType *res;
9496                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9497                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9498                 g_assert (base);
9499                 if (sre_array->rank == 0) //single dimentional array
9500                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9501                 else
9502                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9503                 sre_array->type.type = res;
9504                 return res;
9505         } else if (is_sre_byref (class)) {
9506                 MonoType *res;
9507                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9508                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9509                 g_assert (base);
9510                 res = &mono_class_from_mono_type (base)->this_arg;
9511                 sre_byref->type.type = res;
9512                 return res;
9513         } else if (is_sre_pointer (class)) {
9514                 MonoType *res;
9515                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9516                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9517                 g_assert (base);
9518                 res = &mono_ptr_class_get (base)->byval_arg;
9519                 sre_pointer->type.type = res;
9520                 return res;
9521         } else if (is_sre_generic_instance (class)) {
9522                 MonoType *res, **types;
9523                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9524                 int i, count;
9525
9526                 count = mono_array_length (gclass->type_arguments);
9527                 types = g_new0 (MonoType*, count);
9528                 for (i = 0; i < count; ++i) {
9529                         MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9530                         types [i] = mono_reflection_type_get_handle (t);
9531                         if (!types[i]) {
9532                                 g_free (types);
9533                                 return NULL;
9534                         }
9535                 }
9536
9537                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9538                 g_free (types);
9539                 g_assert (res);
9540                 gclass->type.type = res;
9541                 return res;
9542         }
9543
9544         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9545         return NULL;
9546 }
9547
9548
9549
9550 void
9551 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9552 {
9553         mono_reflection_type_get_handle (type);
9554 }
9555
9556 void
9557 mono_reflection_register_with_runtime (MonoReflectionType *type)
9558 {
9559         MonoType *res = mono_reflection_type_get_handle (type);
9560         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9561         MonoClass *class;
9562
9563         if (!res)
9564                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9565
9566         class = mono_class_from_mono_type (res);
9567
9568         mono_loader_lock (); /*same locking as mono_type_get_object*/
9569         mono_domain_lock (domain);
9570
9571         if (!image_is_dynamic (class->image)) {
9572                 mono_class_setup_supertypes (class);
9573         } else {
9574                 if (!domain->type_hash)
9575                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
9576                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
9577                 mono_g_hash_table_insert (domain->type_hash, res, type);
9578         }
9579         mono_domain_unlock (domain);
9580         mono_loader_unlock ();
9581 }
9582
9583 /**
9584  * LOCKING: Assumes the loader lock is held.
9585  */
9586 static MonoMethodSignature*
9587 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9588         MonoMethodSignature *sig;
9589         int count, i;
9590
9591         count = parameters? mono_array_length (parameters): 0;
9592
9593         sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9594         sig->param_count = count;
9595         sig->sentinelpos = -1; /* FIXME */
9596         for (i = 0; i < count; ++i)
9597                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9598         return sig;
9599 }
9600
9601 /**
9602  * LOCKING: Assumes the loader lock is held.
9603  */
9604 static MonoMethodSignature*
9605 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9606         MonoMethodSignature *sig;
9607
9608         sig = parameters_to_signature (image, ctor->parameters);
9609         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9610         sig->ret = &mono_defaults.void_class->byval_arg;
9611         return sig;
9612 }
9613
9614 /**
9615  * LOCKING: Assumes the loader lock is held.
9616  */
9617 static MonoMethodSignature*
9618 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9619         MonoMethodSignature *sig;
9620
9621         sig = parameters_to_signature (image, method->parameters);
9622         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9623         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9624         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9625         return sig;
9626 }
9627
9628 static MonoMethodSignature*
9629 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9630         MonoMethodSignature *sig;
9631
9632         sig = parameters_to_signature (NULL, method->parameters);
9633         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9634         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9635         sig->generic_param_count = 0;
9636         return sig;
9637 }
9638
9639 static void
9640 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9641 {
9642         MonoClass *klass = mono_object_class (prop);
9643         if (strcmp (klass->name, "PropertyBuilder") == 0) {
9644                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9645                 *name = mono_string_to_utf8 (pb->name);
9646                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9647         } else {
9648                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9649                 *name = g_strdup (p->property->name);
9650                 if (p->property->get)
9651                         *type = mono_method_signature (p->property->get)->ret;
9652                 else
9653                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9654         }
9655 }
9656
9657 static void
9658 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9659 {
9660         MonoClass *klass = mono_object_class (field);
9661         if (strcmp (klass->name, "FieldBuilder") == 0) {
9662                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9663                 *name = mono_string_to_utf8 (fb->name);
9664                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9665         } else {
9666                 MonoReflectionField *f = (MonoReflectionField *)field;
9667                 *name = g_strdup (mono_field_get_name (f->field));
9668                 *type = f->field->type;
9669         }
9670 }
9671
9672 #else /* DISABLE_REFLECTION_EMIT */
9673
9674 void
9675 mono_reflection_register_with_runtime (MonoReflectionType *type)
9676 {
9677         /* This is empty */
9678 }
9679
9680 static gboolean
9681 is_sre_type_builder (MonoClass *class)
9682 {
9683         return FALSE;
9684 }
9685
9686 static gboolean
9687 is_sre_generic_instance (MonoClass *class)
9688 {
9689         return FALSE;
9690 }
9691
9692 static void
9693 init_type_builder_generics (MonoObject *type)
9694 {
9695 }
9696
9697 #endif /* !DISABLE_REFLECTION_EMIT */
9698
9699
9700 static gboolean
9701 is_sr_mono_field (MonoClass *class)
9702 {
9703         check_corlib_type_cached (class, "System.Reflection", "MonoField");
9704 }
9705
9706 static gboolean
9707 is_sr_mono_property (MonoClass *class)
9708 {
9709         check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9710 }
9711
9712 static gboolean
9713 is_sr_mono_method (MonoClass *class)
9714 {
9715         check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9716 }
9717
9718 static gboolean
9719 is_sr_mono_cmethod (MonoClass *class)
9720 {
9721         check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9722 }
9723
9724 static gboolean
9725 is_sr_mono_generic_method (MonoClass *class)
9726 {
9727         check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9728 }
9729
9730 static gboolean
9731 is_sr_mono_generic_cmethod (MonoClass *class)
9732 {
9733         check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9734 }
9735
9736 gboolean
9737 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9738 {
9739         return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9740 }
9741
9742 static gboolean
9743 is_usertype (MonoReflectionType *ref)
9744 {
9745         MonoClass *class = mono_object_class (ref);
9746         return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9747 }
9748
9749 static MonoReflectionType*
9750 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9751 {
9752         if (!type || type->type)
9753                 return type;
9754
9755         if (is_usertype (type)) {
9756                 type = mono_reflection_type_get_underlying_system_type (type);
9757                 if (is_usertype (type))
9758                         mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9759         }
9760
9761         return type;
9762 }
9763 /*
9764  * Encode a value in a custom attribute stream of bytes.
9765  * The value to encode is either supplied as an object in argument val
9766  * (valuetypes are boxed), or as a pointer to the data in the
9767  * argument argval.
9768  * @type represents the type of the value
9769  * @buffer is the start of the buffer
9770  * @p the current position in the buffer
9771  * @buflen contains the size of the buffer and is used to return the new buffer size
9772  * if this needs to be realloced.
9773  * @retbuffer and @retp return the start and the position of the buffer
9774  */
9775 static void
9776 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9777 {
9778         MonoTypeEnum simple_type;
9779         
9780         if ((p-buffer) + 10 >= *buflen) {
9781                 char *newbuf;
9782                 *buflen *= 2;
9783                 newbuf = g_realloc (buffer, *buflen);
9784                 p = newbuf + (p-buffer);
9785                 buffer = newbuf;
9786         }
9787         if (!argval)
9788                 argval = ((char*)arg + sizeof (MonoObject));
9789         simple_type = type->type;
9790 handle_enum:
9791         switch (simple_type) {
9792         case MONO_TYPE_BOOLEAN:
9793         case MONO_TYPE_U1:
9794         case MONO_TYPE_I1:
9795                 *p++ = *argval;
9796                 break;
9797         case MONO_TYPE_CHAR:
9798         case MONO_TYPE_U2:
9799         case MONO_TYPE_I2:
9800                 swap_with_size (p, argval, 2, 1);
9801                 p += 2;
9802                 break;
9803         case MONO_TYPE_U4:
9804         case MONO_TYPE_I4:
9805         case MONO_TYPE_R4:
9806                 swap_with_size (p, argval, 4, 1);
9807                 p += 4;
9808                 break;
9809         case MONO_TYPE_R8:
9810                 swap_with_size (p, argval, 8, 1);
9811                 p += 8;
9812                 break;
9813         case MONO_TYPE_U8:
9814         case MONO_TYPE_I8:
9815                 swap_with_size (p, argval, 8, 1);
9816                 p += 8;
9817                 break;
9818         case MONO_TYPE_VALUETYPE:
9819                 if (type->data.klass->enumtype) {
9820                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
9821                         goto handle_enum;
9822                 } else {
9823                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9824                 }
9825                 break;
9826         case MONO_TYPE_STRING: {
9827                 char *str;
9828                 guint32 slen;
9829                 if (!arg) {
9830                         *p++ = 0xFF;
9831                         break;
9832                 }
9833                 str = mono_string_to_utf8 ((MonoString*)arg);
9834                 slen = strlen (str);
9835                 if ((p-buffer) + 10 + slen >= *buflen) {
9836                         char *newbuf;
9837                         *buflen *= 2;
9838                         *buflen += slen;
9839                         newbuf = g_realloc (buffer, *buflen);
9840                         p = newbuf + (p-buffer);
9841                         buffer = newbuf;
9842                 }
9843                 mono_metadata_encode_value (slen, p, &p);
9844                 memcpy (p, str, slen);
9845                 p += slen;
9846                 g_free (str);
9847                 break;
9848         }
9849         case MONO_TYPE_CLASS: {
9850                 char *str;
9851                 guint32 slen;
9852                 if (!arg) {
9853                         *p++ = 0xFF;
9854                         break;
9855                 }
9856 handle_type:
9857                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9858                 slen = strlen (str);
9859                 if ((p-buffer) + 10 + slen >= *buflen) {
9860                         char *newbuf;
9861                         *buflen *= 2;
9862                         *buflen += slen;
9863                         newbuf = g_realloc (buffer, *buflen);
9864                         p = newbuf + (p-buffer);
9865                         buffer = newbuf;
9866                 }
9867                 mono_metadata_encode_value (slen, p, &p);
9868                 memcpy (p, str, slen);
9869                 p += slen;
9870                 g_free (str);
9871                 break;
9872         }
9873         case MONO_TYPE_SZARRAY: {
9874                 int len, i;
9875                 MonoClass *eclass, *arg_eclass;
9876
9877                 if (!arg) {
9878                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9879                         break;
9880                 }
9881                 len = mono_array_length ((MonoArray*)arg);
9882                 *p++ = len & 0xff;
9883                 *p++ = (len >> 8) & 0xff;
9884                 *p++ = (len >> 16) & 0xff;
9885                 *p++ = (len >> 24) & 0xff;
9886                 *retp = p;
9887                 *retbuffer = buffer;
9888                 eclass = type->data.klass;
9889                 arg_eclass = mono_object_class (arg)->element_class;
9890
9891                 if (!eclass) {
9892                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9893                         eclass = mono_defaults.object_class;
9894                 }
9895                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9896                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9897                         int elsize = mono_class_array_element_size (arg_eclass);
9898                         for (i = 0; i < len; ++i) {
9899                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9900                                 elptr += elsize;
9901                         }
9902                 } else if (eclass->valuetype && arg_eclass->valuetype) {
9903                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9904                         int elsize = mono_class_array_element_size (eclass);
9905                         for (i = 0; i < len; ++i) {
9906                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9907                                 elptr += elsize;
9908                         }
9909                 } else {
9910                         for (i = 0; i < len; ++i) {
9911                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9912                         }
9913                 }
9914                 break;
9915         }
9916         case MONO_TYPE_OBJECT: {
9917                 MonoClass *klass;
9918                 char *str;
9919                 guint32 slen;
9920
9921                 /*
9922                  * The parameter type is 'object' but the type of the actual
9923                  * argument is not. So we have to add type information to the blob
9924                  * too. This is completely undocumented in the spec.
9925                  */
9926
9927                 if (arg == NULL) {
9928                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
9929                         *p++ = 0xFF;
9930                         break;
9931                 }
9932                 
9933                 klass = mono_object_class (arg);
9934
9935                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9936                         *p++ = 0x50;
9937                         goto handle_type;
9938                 } else if (klass->enumtype) {
9939                         *p++ = 0x55;
9940                 } else if (klass == mono_defaults.string_class) {
9941                         simple_type = MONO_TYPE_STRING;
9942                         *p++ = 0x0E;
9943                         goto handle_enum;
9944                 } else if (klass->rank == 1) {
9945                         *p++ = 0x1D;
9946                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9947                                 /* See Partition II, Appendix B3 */
9948                                 *p++ = 0x51;
9949                         else
9950                                 *p++ = klass->element_class->byval_arg.type;
9951                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9952                         break;
9953                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9954                         *p++ = simple_type = klass->byval_arg.type;
9955                         goto handle_enum;
9956                 } else {
9957                         g_error ("unhandled type in custom attr");
9958                 }
9959                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9960                 slen = strlen (str);
9961                 if ((p-buffer) + 10 + slen >= *buflen) {
9962                         char *newbuf;
9963                         *buflen *= 2;
9964                         *buflen += slen;
9965                         newbuf = g_realloc (buffer, *buflen);
9966                         p = newbuf + (p-buffer);
9967                         buffer = newbuf;
9968                 }
9969                 mono_metadata_encode_value (slen, p, &p);
9970                 memcpy (p, str, slen);
9971                 p += slen;
9972                 g_free (str);
9973                 simple_type = mono_class_enum_basetype (klass)->type;
9974                 goto handle_enum;
9975         }
9976         default:
9977                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9978         }
9979         *retp = p;
9980         *retbuffer = buffer;
9981 }
9982
9983 static void
9984 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9985 {
9986         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9987                 char *str = type_get_qualified_name (type, NULL);
9988                 int slen = strlen (str);
9989
9990                 *p++ = 0x55;
9991                 /*
9992                  * This seems to be optional...
9993                  * *p++ = 0x80;
9994                  */
9995                 mono_metadata_encode_value (slen, p, &p);
9996                 memcpy (p, str, slen);
9997                 p += slen;
9998                 g_free (str);
9999         } else if (type->type == MONO_TYPE_OBJECT) {
10000                 *p++ = 0x51;
10001         } else if (type->type == MONO_TYPE_CLASS) {
10002                 /* it should be a type: encode_cattr_value () has the check */
10003                 *p++ = 0x50;
10004         } else {
10005                 mono_metadata_encode_value (type->type, p, &p);
10006                 if (type->type == MONO_TYPE_SZARRAY)
10007                         /* See the examples in Partition VI, Annex B */
10008                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10009         }
10010
10011         *retp = p;
10012 }
10013
10014 #ifndef DISABLE_REFLECTION_EMIT
10015 static void
10016 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10017 {
10018         int len;
10019         /* Preallocate a large enough buffer */
10020         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10021                 char *str = type_get_qualified_name (type, NULL);
10022                 len = strlen (str);
10023                 g_free (str);
10024         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10025                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10026                 len = strlen (str);
10027                 g_free (str);
10028         } else {
10029                 len = 0;
10030         }
10031         len += strlen (name);
10032
10033         if ((p-buffer) + 20 + len >= *buflen) {
10034                 char *newbuf;
10035                 *buflen *= 2;
10036                 *buflen += len;
10037                 newbuf = g_realloc (buffer, *buflen);
10038                 p = newbuf + (p-buffer);
10039                 buffer = newbuf;
10040         }
10041
10042         encode_field_or_prop_type (type, p, &p);
10043
10044         len = strlen (name);
10045         mono_metadata_encode_value (len, p, &p);
10046         memcpy (p, name, len);
10047         p += len;
10048         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10049         *retp = p;
10050         *retbuffer = buffer;
10051 }
10052
10053 /*
10054  * mono_reflection_get_custom_attrs_blob:
10055  * @ctor: custom attribute constructor
10056  * @ctorArgs: arguments o the constructor
10057  * @properties:
10058  * @propValues:
10059  * @fields:
10060  * @fieldValues:
10061  * 
10062  * Creates the blob of data that needs to be saved in the metadata and that represents
10063  * the custom attributed described by @ctor, @ctorArgs etc.
10064  * Returns: a Byte array representing the blob of data.
10065  */
10066 MonoArray*
10067 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10068 {
10069         MonoArray *result;
10070         MonoMethodSignature *sig;
10071         MonoObject *arg;
10072         char *buffer, *p;
10073         guint32 buflen, i;
10074
10075         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10076                 /* sig is freed later so allocate it in the heap */
10077                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10078         } else {
10079                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10080         }
10081
10082         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10083         buflen = 256;
10084         p = buffer = g_malloc (buflen);
10085         /* write the prolog */
10086         *p++ = 1;
10087         *p++ = 0;
10088         for (i = 0; i < sig->param_count; ++i) {
10089                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10090                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10091         }
10092         i = 0;
10093         if (properties)
10094                 i += mono_array_length (properties);
10095         if (fields)
10096                 i += mono_array_length (fields);
10097         *p++ = i & 0xff;
10098         *p++ = (i >> 8) & 0xff;
10099         if (properties) {
10100                 MonoObject *prop;
10101                 for (i = 0; i < mono_array_length (properties); ++i) {
10102                         MonoType *ptype;
10103                         char *pname;
10104
10105                         prop = mono_array_get (properties, gpointer, i);
10106                         get_prop_name_and_type (prop, &pname, &ptype);
10107                         *p++ = 0x54; /* PROPERTY signature */
10108                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10109                         g_free (pname);
10110                 }
10111         }
10112
10113         if (fields) {
10114                 MonoObject *field;
10115                 for (i = 0; i < mono_array_length (fields); ++i) {
10116                         MonoType *ftype;
10117                         char *fname;
10118
10119                         field = mono_array_get (fields, gpointer, i);
10120                         get_field_name_and_type (field, &fname, &ftype);
10121                         *p++ = 0x53; /* FIELD signature */
10122                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10123                         g_free (fname);
10124                 }
10125         }
10126
10127         g_assert (p - buffer <= buflen);
10128         buflen = p - buffer;
10129         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10130         p = mono_array_addr (result, char, 0);
10131         memcpy (p, buffer, buflen);
10132         g_free (buffer);
10133         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10134                 g_free (sig);
10135         return result;
10136 }
10137
10138 /*
10139  * mono_reflection_setup_internal_class:
10140  * @tb: a TypeBuilder object
10141  *
10142  * Creates a MonoClass that represents the TypeBuilder.
10143  * This is a trick that lets us simplify a lot of reflection code
10144  * (and will allow us to support Build and Run assemblies easier).
10145  */
10146 void
10147 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10148 {
10149         MonoError error;
10150         MonoClass *klass, *parent;
10151
10152         RESOLVE_TYPE (tb->parent);
10153
10154         mono_loader_lock ();
10155
10156         if (tb->parent) {
10157                 /* check so we can compile corlib correctly */
10158                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10159                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10160                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10161                 } else {
10162                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10163                 }
10164         } else {
10165                 parent = NULL;
10166         }
10167         
10168         /* the type has already being created: it means we just have to change the parent */
10169         if (tb->type.type) {
10170                 klass = mono_class_from_mono_type (tb->type.type);
10171                 klass->parent = NULL;
10172                 /* fool mono_class_setup_parent */
10173                 klass->supertypes = NULL;
10174                 mono_class_setup_parent (klass, parent);
10175                 mono_class_setup_mono_type (klass);
10176                 mono_loader_unlock ();
10177                 return;
10178         }
10179
10180         klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10181
10182         klass->image = &tb->module->dynamic_image->image;
10183
10184         klass->inited = 1; /* we lie to the runtime */
10185         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10186         if (!mono_error_ok (&error))
10187                 goto failure;
10188         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10189         if (!mono_error_ok (&error))
10190                 goto failure;
10191         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10192         klass->flags = tb->attrs;
10193         
10194         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10195
10196         klass->element_class = klass;
10197
10198         if (mono_class_get_ref_info (klass) == NULL) {
10199
10200                 mono_class_set_ref_info (klass, tb);
10201
10202                 /* Put into cache so mono_class_get_checked () will find it.
10203                 Skip nested types as those should not be available on the global scope. */
10204                 if (!tb->nesting_type)
10205                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10206
10207                 /*
10208                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10209                 by performing a mono_class_get which does the full resolution.
10210
10211                 Working around this semantics would require us to write a lot of code for no clear advantage.
10212                 */
10213                 mono_image_append_class_to_reflection_info_set (klass);
10214         } else {
10215                 g_assert (mono_class_get_ref_info (klass) == tb);
10216         }
10217
10218         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10219
10220         if (parent != NULL) {
10221                 mono_class_setup_parent (klass, parent);
10222         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10223                 const char *old_n = klass->name;
10224                 /* trick to get relative numbering right when compiling corlib */
10225                 klass->name = "BuildingObject";
10226                 mono_class_setup_parent (klass, mono_defaults.object_class);
10227                 klass->name = old_n;
10228         }
10229
10230         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10231                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10232                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10233                 klass->instance_size = sizeof (MonoObject);
10234                 klass->size_inited = 1;
10235                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10236         }
10237
10238         mono_class_setup_mono_type (klass);
10239
10240         mono_class_setup_supertypes (klass);
10241
10242         /*
10243          * FIXME: handle interfaces.
10244          */
10245
10246         tb->type.type = &klass->byval_arg;
10247
10248         if (tb->nesting_type) {
10249                 g_assert (tb->nesting_type->type);
10250                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10251         }
10252
10253         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10254
10255         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10256         
10257         mono_loader_unlock ();
10258         return;
10259
10260 failure:
10261         mono_loader_unlock ();
10262         mono_error_raise_exception (&error);
10263 }
10264
10265 /*
10266  * mono_reflection_setup_generic_class:
10267  * @tb: a TypeBuilder object
10268  *
10269  * Setup the generic class before adding the first generic parameter.
10270  */
10271 void
10272 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10273 {
10274 }
10275
10276 /*
10277  * mono_reflection_create_generic_class:
10278  * @tb: a TypeBuilder object
10279  *
10280  * Creates the generic class after all generic parameters have been added.
10281  */
10282 void
10283 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10284 {
10285         MonoClass *klass;
10286         int count, i;
10287
10288         klass = mono_class_from_mono_type (tb->type.type);
10289
10290         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10291
10292         if (klass->generic_container || (count == 0))
10293                 return;
10294
10295         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10296
10297         klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10298
10299         klass->generic_container->owner.klass = klass;
10300         klass->generic_container->type_argc = count;
10301         klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10302
10303         klass->is_generic = 1;
10304
10305         for (i = 0; i < count; i++) {
10306                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
10307                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10308                 klass->generic_container->type_params [i] = *param;
10309                 /*Make sure we are a diferent type instance */
10310                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10311                 klass->generic_container->type_params [i].info.pklass = NULL;
10312                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10313
10314                 g_assert (klass->generic_container->type_params [i].param.owner);
10315         }
10316
10317         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10318 }
10319
10320 /*
10321  * mono_reflection_create_internal_class:
10322  * @tb: a TypeBuilder object
10323  *
10324  * Actually create the MonoClass that is associated with the TypeBuilder.
10325  */
10326 void
10327 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
10328 {
10329         MonoClass *klass;
10330
10331         klass = mono_class_from_mono_type (tb->type.type);
10332
10333         mono_loader_lock ();
10334         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
10335                 MonoReflectionFieldBuilder *fb;
10336                 MonoClass *ec;
10337                 MonoType *enum_basetype;
10338
10339                 g_assert (tb->fields != NULL);
10340                 g_assert (mono_array_length (tb->fields) >= 1);
10341
10342                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
10343
10344                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
10345                         mono_loader_unlock ();
10346                         return;
10347                 }
10348
10349                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10350                 klass->element_class = mono_class_from_mono_type (enum_basetype);
10351                 if (!klass->element_class)
10352                         klass->element_class = mono_class_from_mono_type (enum_basetype);
10353
10354                 /*
10355                  * get the element_class from the current corlib.
10356                  */
10357                 ec = default_class_from_mono_type (enum_basetype);
10358                 klass->instance_size = ec->instance_size;
10359                 klass->size_inited = 1;
10360                 /* 
10361                  * this is almost safe to do with enums and it's needed to be able
10362                  * to create objects of the enum type (for use in SetConstant).
10363                  */
10364                 /* FIXME: Does this mean enums can't have method overrides ? */
10365                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10366         }
10367         mono_loader_unlock ();
10368 }
10369
10370 static MonoMarshalSpec*
10371 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
10372                                                                 MonoReflectionMarshal *minfo)
10373 {
10374         MonoMarshalSpec *res;
10375
10376         res = image_g_new0 (image, MonoMarshalSpec, 1);
10377         res->native = minfo->type;
10378
10379         switch (minfo->type) {
10380         case MONO_NATIVE_LPARRAY:
10381                 res->data.array_data.elem_type = minfo->eltype;
10382                 if (minfo->has_size) {
10383                         res->data.array_data.param_num = minfo->param_num;
10384                         res->data.array_data.num_elem = minfo->count;
10385                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
10386                 }
10387                 else {
10388                         res->data.array_data.param_num = -1;
10389                         res->data.array_data.num_elem = -1;
10390                         res->data.array_data.elem_mult = -1;
10391                 }
10392                 break;
10393
10394         case MONO_NATIVE_BYVALTSTR:
10395         case MONO_NATIVE_BYVALARRAY:
10396                 res->data.array_data.num_elem = minfo->count;
10397                 break;
10398
10399         case MONO_NATIVE_CUSTOM:
10400                 if (minfo->marshaltyperef)
10401                         res->data.custom_data.custom_name =
10402                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
10403                 if (minfo->mcookie)
10404                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
10405                 break;
10406
10407         default:
10408                 break;
10409         }
10410
10411         return res;
10412 }
10413 #endif /* !DISABLE_REFLECTION_EMIT */
10414
10415 MonoReflectionMarshalAsAttribute*
10416 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
10417                                                                                    MonoMarshalSpec *spec)
10418 {
10419         static MonoClass *System_Reflection_Emit_MarshalAsAttribute;
10420         MonoReflectionMarshalAsAttribute *minfo;
10421         MonoType *mtype;
10422
10423         if (!System_Reflection_Emit_MarshalAsAttribute) {
10424                 System_Reflection_Emit_MarshalAsAttribute = mono_class_from_name (
10425                    mono_defaults.corlib, "System.Runtime.InteropServices", "MarshalAsAttribute");
10426                 g_assert (System_Reflection_Emit_MarshalAsAttribute);
10427         }
10428
10429         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new (domain, System_Reflection_Emit_MarshalAsAttribute);
10430         minfo->utype = spec->native;
10431
10432         switch (minfo->utype) {
10433         case MONO_NATIVE_LPARRAY:
10434                 minfo->array_subtype = spec->data.array_data.elem_type;
10435                 minfo->size_const = spec->data.array_data.num_elem;
10436                 if (spec->data.array_data.param_num != -1)
10437                         minfo->size_param_index = spec->data.array_data.param_num;
10438                 break;
10439
10440         case MONO_NATIVE_BYVALTSTR:
10441         case MONO_NATIVE_BYVALARRAY:
10442                 minfo->size_const = spec->data.array_data.num_elem;
10443                 break;
10444
10445         case MONO_NATIVE_CUSTOM:
10446                 if (spec->data.custom_data.custom_name) {
10447                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10448                         if (mtype)
10449                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, mono_type_get_object (domain, mtype));
10450
10451                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
10452                 }
10453                 if (spec->data.custom_data.cookie)
10454                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
10455                 break;
10456
10457         default:
10458                 break;
10459         }
10460
10461         return minfo;
10462 }
10463
10464 #ifndef DISABLE_REFLECTION_EMIT
10465 static MonoMethod*
10466 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10467                                          ReflectionMethodBuilder *rmb,
10468                                          MonoMethodSignature *sig)
10469 {
10470         MonoError error;
10471         MonoMethod *m;
10472         MonoMethodWrapper *wrapperm;
10473         MonoMarshalSpec **specs;
10474         MonoReflectionMethodAux *method_aux;
10475         MonoImage *image;
10476         gboolean dynamic;
10477         int i;
10478
10479         mono_error_init (&error);
10480         /*
10481          * Methods created using a MethodBuilder should have their memory allocated
10482          * inside the image mempool, while dynamic methods should have their memory
10483          * malloc'd.
10484          */
10485         dynamic = rmb->refs != NULL;
10486         image = dynamic ? NULL : klass->image;
10487
10488         if (!dynamic)
10489                 g_assert (!klass->generic_class);
10490
10491         mono_loader_lock ();
10492
10493         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10494                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10495                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10496         else
10497                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10498
10499         wrapperm = (MonoMethodWrapper*)m;
10500
10501         m->dynamic = dynamic;
10502         m->slot = -1;
10503         m->flags = rmb->attrs;
10504         m->iflags = rmb->iattrs;
10505         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10506         m->klass = klass;
10507         m->signature = sig;
10508         m->sre_method = TRUE;
10509         m->skip_visibility = rmb->skip_visibility;
10510         if (rmb->table_idx)
10511                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10512
10513         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10514                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10515                         m->string_ctor = 1;
10516
10517                 m->signature->pinvoke = 1;
10518         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10519                 m->signature->pinvoke = 1;
10520
10521                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10522
10523                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10524                 g_assert (mono_error_ok (&error));
10525                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10526                 g_assert (mono_error_ok (&error));
10527                 
10528                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10529
10530                 if (image_is_dynamic (klass->image))
10531                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10532
10533                 mono_loader_unlock ();
10534
10535                 return m;
10536         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10537                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10538                 MonoMethodHeader *header;
10539                 guint32 code_size;
10540                 gint32 max_stack, i;
10541                 gint32 num_locals = 0;
10542                 gint32 num_clauses = 0;
10543                 guint8 *code;
10544
10545                 if (rmb->ilgen) {
10546                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10547                         code_size = rmb->ilgen->code_len;
10548                         max_stack = rmb->ilgen->max_stack;
10549                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10550                         if (rmb->ilgen->ex_handlers)
10551                                 num_clauses = method_count_clauses (rmb->ilgen);
10552                 } else {
10553                         if (rmb->code) {
10554                                 code = mono_array_addr (rmb->code, guint8, 0);
10555                                 code_size = mono_array_length (rmb->code);
10556                                 /* we probably need to run a verifier on the code... */
10557                                 max_stack = 8; 
10558                         }
10559                         else {
10560                                 code = NULL;
10561                                 code_size = 0;
10562                                 max_stack = 8;
10563                         }
10564                 }
10565
10566                 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10567                 header->code_size = code_size;
10568                 header->code = image_g_malloc (image, code_size);
10569                 memcpy ((char*)header->code, code, code_size);
10570                 header->max_stack = max_stack;
10571                 header->init_locals = rmb->init_locals;
10572                 header->num_locals = num_locals;
10573
10574                 for (i = 0; i < num_locals; ++i) {
10575                         MonoReflectionLocalBuilder *lb = 
10576                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10577
10578                         header->locals [i] = image_g_new0 (image, MonoType, 1);
10579                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10580                 }
10581
10582                 header->num_clauses = num_clauses;
10583                 if (num_clauses) {
10584                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10585                                  rmb->ilgen, num_clauses);
10586                 }
10587
10588                 wrapperm->header = header;
10589         }
10590
10591         if (rmb->generic_params) {
10592                 int count = mono_array_length (rmb->generic_params);
10593                 MonoGenericContainer *container = rmb->generic_container;
10594
10595                 g_assert (container);
10596
10597                 container->type_argc = count;
10598                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10599                 container->owner.method = m;
10600
10601                 m->is_generic = TRUE;
10602                 mono_method_set_generic_container (m, container);
10603
10604                 for (i = 0; i < count; i++) {
10605                         MonoReflectionGenericParam *gp =
10606                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10607                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10608                         container->type_params [i] = *param;
10609                 }
10610
10611                 /*
10612                  * The method signature might have pointers to generic parameters that belong to other methods.
10613                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10614                  * generic parameters.
10615                  */
10616                 for (i = 0; i < m->signature->param_count; ++i) {
10617                         MonoType *t = m->signature->params [i];
10618                         if (t->type == MONO_TYPE_MVAR) {
10619                                 MonoGenericParam *gparam =  t->data.generic_param;
10620                                 if (gparam->num < count) {
10621                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10622                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10623                                 }
10624
10625                         }
10626                 }
10627
10628                 if (klass->generic_container) {
10629                         container->parent = klass->generic_container;
10630                         container->context.class_inst = klass->generic_container->context.class_inst;
10631                 }
10632                 container->context.method_inst = mono_get_shared_generic_inst (container);
10633         }
10634
10635         if (rmb->refs) {
10636                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10637                 int i;
10638                 void **data;
10639
10640                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10641
10642                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10643                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10644                 for (i = 0; i < rmb->nrefs; ++i)
10645                         data [i + 1] = rmb->refs [i];
10646         }
10647
10648         method_aux = NULL;
10649
10650         /* Parameter info */
10651         if (rmb->pinfo) {
10652                 if (!method_aux)
10653                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10654                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10655                 for (i = 0; i <= m->signature->param_count; ++i) {
10656                         MonoReflectionParamBuilder *pb;
10657                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10658                                 if ((i > 0) && (pb->attrs)) {
10659                                         /* Make a copy since it might point to a shared type structure */
10660                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10661                                         m->signature->params [i - 1]->attrs = pb->attrs;
10662                                 }
10663
10664                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10665                                         MonoDynamicImage *assembly;
10666                                         guint32 idx, def_type, len;
10667                                         char *p;
10668                                         const char *p2;
10669
10670                                         if (!method_aux->param_defaults) {
10671                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10672                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10673                                         }
10674                                         assembly = (MonoDynamicImage*)klass->image;
10675                                         idx = encode_constant (assembly, pb->def_value, &def_type);
10676                                         /* Copy the data from the blob since it might get realloc-ed */
10677                                         p = assembly->blob.data + idx;
10678                                         len = mono_metadata_decode_blob_size (p, &p2);
10679                                         len += p2 - p;
10680                                         method_aux->param_defaults [i] = image_g_malloc (image, len);
10681                                         method_aux->param_default_types [i] = def_type;
10682                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10683                                 }
10684
10685                                 if (pb->name) {
10686                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10687                                         g_assert (mono_error_ok (&error));
10688                                 }
10689                                 if (pb->cattrs) {
10690                                         if (!method_aux->param_cattr)
10691                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10692                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10693                                 }
10694                         }
10695                 }
10696         }
10697
10698         /* Parameter marshalling */
10699         specs = NULL;
10700         if (rmb->pinfo)         
10701                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10702                         MonoReflectionParamBuilder *pb;
10703                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10704                                 if (pb->marshal_info) {
10705                                         if (specs == NULL)
10706                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10707                                         specs [pb->position] = 
10708                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10709                                 }
10710                         }
10711                 }
10712         if (specs != NULL) {
10713                 if (!method_aux)
10714                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10715                 method_aux->param_marshall = specs;
10716         }
10717
10718         if (image_is_dynamic (klass->image) && method_aux)
10719                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10720
10721         mono_loader_unlock ();
10722
10723         return m;
10724 }       
10725
10726 static MonoMethod*
10727 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10728 {
10729         ReflectionMethodBuilder rmb;
10730         MonoMethodSignature *sig;
10731
10732         mono_loader_lock ();
10733         sig = ctor_builder_to_signature (klass->image, mb);
10734         mono_loader_unlock ();
10735
10736         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10737
10738         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10739         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10740
10741         /* If we are in a generic class, we might be called multiple times from inflate_method */
10742         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10743                 /* ilgen is no longer needed */
10744                 mb->ilgen = NULL;
10745         }
10746
10747         return mb->mhandle;
10748 }
10749
10750 static MonoMethod*
10751 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10752 {
10753         ReflectionMethodBuilder rmb;
10754         MonoMethodSignature *sig;
10755
10756         mono_loader_lock ();
10757         sig = method_builder_to_signature (klass->image, mb);
10758         mono_loader_unlock ();
10759
10760         reflection_methodbuilder_from_method_builder (&rmb, mb);
10761
10762         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10763         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10764
10765         /* If we are in a generic class, we might be called multiple times from inflate_method */
10766         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10767                 /* ilgen is no longer needed */
10768                 mb->ilgen = NULL;
10769         }
10770         return mb->mhandle;
10771 }
10772
10773 static MonoClassField*
10774 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10775 {
10776         MonoClassField *field;
10777         MonoType *custom;
10778         MonoError error;
10779
10780         field = g_new0 (MonoClassField, 1);
10781
10782         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10783         g_assert (mono_error_ok (&error));
10784         if (fb->attrs || fb->modreq || fb->modopt) {
10785                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10786                 field->type->attrs = fb->attrs;
10787
10788                 g_assert (image_is_dynamic (klass->image));
10789                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10790                 g_free (field->type);
10791                 field->type = mono_metadata_type_dup (klass->image, custom);
10792                 g_free (custom);
10793         } else {
10794                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10795         }
10796         if (fb->offset != -1)
10797                 field->offset = fb->offset;
10798         field->parent = klass;
10799         mono_save_custom_attrs (klass->image, field, fb->cattrs);
10800
10801         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10802
10803         return field;
10804 }
10805 #endif
10806
10807 MonoType*
10808 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10809 {
10810         MonoClass *klass;
10811         MonoReflectionTypeBuilder *tb = NULL;
10812         gboolean is_dynamic = FALSE;
10813         MonoClass *geninst;
10814
10815         mono_loader_lock ();
10816
10817         if (is_sre_type_builder (mono_object_class (type))) {
10818                 tb = (MonoReflectionTypeBuilder *) type;
10819
10820                 is_dynamic = TRUE;
10821         } else if (is_sre_generic_instance (mono_object_class (type))) {
10822                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10823                 MonoReflectionType *gtd = rgi->generic_type;
10824
10825                 if (is_sre_type_builder (mono_object_class (gtd))) {
10826                         tb = (MonoReflectionTypeBuilder *)gtd;
10827                         is_dynamic = TRUE;
10828                 }
10829         }
10830
10831         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10832         if (tb && tb->generic_container)
10833                 mono_reflection_create_generic_class (tb);
10834
10835         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10836         if (!klass->generic_container) {
10837                 mono_loader_unlock ();
10838                 return NULL;
10839         }
10840
10841         if (klass->wastypebuilder) {
10842                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10843
10844                 is_dynamic = TRUE;
10845         }
10846
10847         mono_loader_unlock ();
10848
10849         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10850
10851         return &geninst->byval_arg;
10852 }
10853
10854 MonoClass*
10855 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10856 {
10857         MonoGenericClass *gclass;
10858         MonoGenericInst *inst;
10859
10860         g_assert (klass->generic_container);
10861
10862         inst = mono_metadata_get_generic_inst (type_argc, types);
10863         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10864
10865         return mono_generic_class_get_class (gclass);
10866 }
10867
10868 MonoReflectionMethod*
10869 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10870 {
10871         MonoError error;
10872         MonoClass *klass;
10873         MonoMethod *method, *inflated;
10874         MonoMethodInflated *imethod;
10875         MonoGenericContext tmp_context;
10876         MonoGenericInst *ginst;
10877         MonoType **type_argv;
10878         int count, i;
10879
10880         /*FIXME but this no longer should happen*/
10881         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10882 #ifndef DISABLE_REFLECTION_EMIT
10883                 MonoReflectionMethodBuilder *mb = NULL;
10884                 MonoReflectionTypeBuilder *tb;
10885                 MonoClass *klass;
10886
10887                 mb = (MonoReflectionMethodBuilder *) rmethod;
10888                 tb = (MonoReflectionTypeBuilder *) mb->type;
10889                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10890
10891                 method = methodbuilder_to_mono_method (klass, mb);
10892 #else
10893                 g_assert_not_reached ();
10894                 method = NULL;
10895 #endif
10896         } else {
10897                 method = rmethod->method;
10898         }
10899
10900         klass = method->klass;
10901
10902         if (method->is_inflated)
10903                 method = ((MonoMethodInflated *) method)->declaring;
10904
10905         count = mono_method_signature (method)->generic_param_count;
10906         if (count != mono_array_length (types))
10907                 return NULL;
10908
10909         type_argv = g_new0 (MonoType *, count);
10910         for (i = 0; i < count; i++) {
10911                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10912                 type_argv [i] = mono_reflection_type_get_handle (garg);
10913         }
10914         ginst = mono_metadata_get_generic_inst (count, type_argv);
10915         g_free (type_argv);
10916
10917         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10918         tmp_context.method_inst = ginst;
10919
10920         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
10921         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10922         imethod = (MonoMethodInflated *) inflated;
10923
10924         /*FIXME but I think this is no longer necessary*/
10925         if (image_is_dynamic (method->klass->image)) {
10926                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10927                 /*
10928                  * This table maps metadata structures representing inflated methods/fields
10929                  * to the reflection objects representing their generic definitions.
10930                  */
10931                 mono_image_lock ((MonoImage*)image);
10932                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10933                 mono_image_unlock ((MonoImage*)image);
10934         }
10935
10936         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10937                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10938         
10939         return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10940 }
10941
10942 #ifndef DISABLE_REFLECTION_EMIT
10943
10944 static MonoMethod *
10945 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10946 {
10947         MonoMethodInflated *imethod;
10948         MonoGenericContext *context;
10949         int i;
10950
10951         /*
10952          * With generic code sharing the klass might not be inflated.
10953          * This can happen because classes inflated with their own
10954          * type arguments are "normalized" to the uninflated class.
10955          */
10956         if (!klass->generic_class)
10957                 return method;
10958
10959         context = mono_class_get_context (klass);
10960
10961         if (klass->method.count && klass->methods) {
10962                 /* Find the already created inflated method */
10963                 for (i = 0; i < klass->method.count; ++i) {
10964                         g_assert (klass->methods [i]->is_inflated);
10965                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10966                                 break;
10967                 }
10968                 g_assert (i < klass->method.count);
10969                 imethod = (MonoMethodInflated*)klass->methods [i];
10970         } else {
10971                 MonoError error;
10972                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
10973                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
10974         }
10975
10976         if (method->is_generic && image_is_dynamic (method->klass->image)) {
10977                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10978
10979                 mono_image_lock ((MonoImage*)image);
10980                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10981                 mono_image_unlock ((MonoImage*)image);
10982         }
10983         return (MonoMethod *) imethod;
10984 }
10985
10986 static MonoMethod *
10987 inflate_method (MonoReflectionType *type, MonoObject *obj)
10988 {
10989         MonoMethod *method;
10990         MonoClass *gklass;
10991
10992         MonoClass *type_class = mono_object_class (type);
10993
10994         if (is_sre_generic_instance (type_class)) {
10995                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10996                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10997         } else if (is_sre_type_builder (type_class)) {
10998                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10999         } else if (type->type) {
11000                 gklass = mono_class_from_mono_type (type->type);
11001                 gklass = mono_class_get_generic_type_definition (gklass);
11002         } else {
11003                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11004         }
11005
11006         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11007                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11008                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11009                 else
11010                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
11011         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
11012                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
11013         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11014                 method = ((MonoReflectionMethod *) obj)->method;
11015         else {
11016                 method = NULL; /* prevent compiler warning */
11017                 g_error ("can't handle type %s", obj->vtable->klass->name);
11018         }
11019
11020         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11021 }
11022
11023 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11024 void
11025 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11026 {
11027         MonoGenericClass *gclass;
11028         MonoDynamicGenericClass *dgclass;
11029         MonoClass *klass, *gklass;
11030         MonoType *gtype;
11031         int i;
11032
11033         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11034         klass = mono_class_from_mono_type (gtype);
11035         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11036         gclass = gtype->data.generic_class;
11037
11038         if (!gclass->is_dynamic)
11039                 return;
11040
11041         dgclass = (MonoDynamicGenericClass *) gclass;
11042
11043         if (dgclass->initialized)
11044                 return;
11045
11046         gklass = gclass->container_class;
11047         mono_class_init (gklass);
11048
11049         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11050
11051         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11052         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11053         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11054
11055         for (i = 0; i < dgclass->count_fields; i++) {
11056                 MonoObject *obj = mono_array_get (fields, gpointer, i);
11057                 MonoClassField *field, *inflated_field = NULL;
11058
11059                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11060                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11061                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11062                         field = ((MonoReflectionField *) obj)->field;
11063                 else {
11064                         field = NULL; /* prevent compiler warning */
11065                         g_assert_not_reached ();
11066                 }
11067
11068                 dgclass->fields [i] = *field;
11069                 dgclass->fields [i].parent = klass;
11070                 dgclass->fields [i].type = mono_class_inflate_generic_type (
11071                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11072                 dgclass->field_generic_types [i] = field->type;
11073                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11074                 dgclass->field_objects [i] = obj;
11075
11076                 if (inflated_field) {
11077                         g_free (inflated_field);
11078                 } else {
11079                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11080                 }
11081         }
11082
11083         dgclass->initialized = TRUE;
11084 }
11085
11086 void
11087 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11088 {
11089         MonoDynamicGenericClass *dgclass;
11090         int i;
11091
11092         g_assert (gclass->is_dynamic);
11093
11094         dgclass = (MonoDynamicGenericClass *)gclass;
11095
11096         for (i = 0; i < dgclass->count_fields; ++i) {
11097                 MonoClassField *field = dgclass->fields + i;
11098                 mono_metadata_free_type (field->type);
11099                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11100         }
11101 }
11102
11103 static void
11104 fix_partial_generic_class (MonoClass *klass)
11105 {
11106         MonoClass *gklass = klass->generic_class->container_class;
11107         MonoDynamicGenericClass *dgclass;
11108         int i;
11109
11110         if (klass->wastypebuilder)
11111                 return;
11112
11113         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11114         if (klass->parent != gklass->parent) {
11115                 MonoError error;
11116                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11117                 if (mono_error_ok (&error)) {
11118                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11119                         mono_metadata_free_type (parent_type);
11120                         if (parent != klass->parent) {
11121                                 /*fool mono_class_setup_parent*/
11122                                 klass->supertypes = NULL;
11123                                 mono_class_setup_parent (klass, parent);
11124                         }
11125                 } else {
11126                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11127                         mono_error_cleanup (&error);
11128                         if (gklass->wastypebuilder)
11129                                 klass->wastypebuilder = TRUE;
11130                         return;
11131                 }
11132         }
11133
11134         if (!dgclass->initialized)
11135                 return;
11136
11137         if (klass->method.count != gklass->method.count) {
11138                 klass->method.count = gklass->method.count;
11139                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11140
11141                 for (i = 0; i < klass->method.count; i++) {
11142                         MonoError error;
11143                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11144                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11145                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11146                 }
11147         }
11148
11149         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11150                 klass->interface_count = gklass->interface_count;
11151                 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11152                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11153
11154                 for (i = 0; i < gklass->interface_count; ++i) {
11155                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11156                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11157                         mono_metadata_free_type (iface_type);
11158
11159                         ensure_runtime_vtable (klass->interfaces [i]);
11160                 }
11161                 klass->interfaces_inited = 1;
11162         }
11163
11164         if (klass->field.count != gklass->field.count) {
11165                 klass->field.count = gklass->field.count;
11166                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11167
11168                 for (i = 0; i < klass->field.count; i++) {
11169                         klass->fields [i] = gklass->fields [i];
11170                         klass->fields [i].parent = klass;
11171                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11172                 }
11173         }
11174
11175         /*We can only finish with this klass once it's parent has as well*/
11176         if (gklass->wastypebuilder)
11177                 klass->wastypebuilder = TRUE;
11178         return;
11179 }
11180
11181 static void
11182 ensure_generic_class_runtime_vtable (MonoClass *klass)
11183 {
11184         MonoClass *gklass = klass->generic_class->container_class;
11185
11186         ensure_runtime_vtable (gklass); 
11187
11188         fix_partial_generic_class (klass);
11189 }
11190
11191 static void
11192 ensure_runtime_vtable (MonoClass *klass)
11193 {
11194         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11195         int i, num, j;
11196
11197         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11198                 return;
11199         if (klass->parent)
11200                 ensure_runtime_vtable (klass->parent);
11201
11202         if (tb) {
11203                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11204                 num += tb->num_methods;
11205                 klass->method.count = num;
11206                 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11207                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11208                 for (i = 0; i < num; ++i)
11209                         klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
11210                 num = tb->num_methods;
11211                 j = i;
11212                 for (i = 0; i < num; ++i)
11213                         klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
11214         
11215                 if (tb->interfaces) {
11216                         klass->interface_count = mono_array_length (tb->interfaces);
11217                         klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11218                         for (i = 0; i < klass->interface_count; ++i) {
11219                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11220                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11221                                 ensure_runtime_vtable (klass->interfaces [i]);
11222                         }
11223                         klass->interfaces_inited = 1;
11224                 }
11225         } else if (klass->generic_class){
11226                 ensure_generic_class_runtime_vtable (klass);
11227         }
11228
11229         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11230                 int slot_num = 0;
11231                 for (i = 0; i < klass->method.count; ++i) {
11232                         MonoMethod *im = klass->methods [i];
11233                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11234                                 im->slot = slot_num++;
11235                 }
11236                 
11237                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11238                 mono_class_setup_interface_offsets (klass);
11239                 mono_class_setup_interface_id (klass);
11240         }
11241
11242         /*
11243          * The generic vtable is needed even if image->run is not set since some
11244          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11245          * method->slot being defined.
11246          */
11247
11248         /* 
11249          * tb->methods could not be freed since it is used for determining 
11250          * overrides during dynamic vtable construction.
11251          */
11252 }
11253
11254 static MonoMethod*
11255 mono_reflection_method_get_handle (MonoObject *method)
11256 {
11257         MonoClass *class = mono_object_class (method);
11258         if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
11259                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
11260                 return sr_method->method;
11261         }
11262         if (is_sre_method_builder (class)) {
11263                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
11264                 return mb->mhandle;
11265         }
11266         if (is_sre_method_on_tb_inst (class)) {
11267                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
11268                 MonoMethod *result;
11269                 /*FIXME move this to a proper method and unify with resolve_object*/
11270                 if (m->method_args) {
11271                         result = mono_reflection_method_on_tb_inst_get_handle (m);
11272                 } else {
11273                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
11274                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
11275                         MonoMethod *mono_method;
11276
11277                         if (is_sre_method_builder (mono_object_class (m->mb)))
11278                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11279                         else if (is_sr_mono_method (mono_object_class (m->mb)))
11280                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
11281                         else
11282                                 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)));
11283
11284                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
11285                 }
11286                 return result;
11287         }
11288
11289         g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
11290         return NULL;
11291 }
11292
11293 void
11294 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11295 {
11296         MonoReflectionTypeBuilder *tb;
11297         int i, j, onum;
11298         MonoReflectionMethod *m;
11299
11300         *overrides = NULL;
11301         *num_overrides = 0;
11302
11303         g_assert (image_is_dynamic (klass->image));
11304
11305         if (!mono_class_get_ref_info (klass))
11306                 return;
11307
11308         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
11309
11310         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
11311
11312         onum = 0;
11313         if (tb->methods) {
11314                 for (i = 0; i < tb->num_methods; ++i) {
11315                         MonoReflectionMethodBuilder *mb = 
11316                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11317                         if (mb->override_methods)
11318                                 onum += mono_array_length (mb->override_methods);
11319                 }
11320         }
11321
11322         if (onum) {
11323                 *overrides = g_new0 (MonoMethod*, onum * 2);
11324
11325                 onum = 0;
11326                 for (i = 0; i < tb->num_methods; ++i) {
11327                         MonoReflectionMethodBuilder *mb = 
11328                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
11329                         if (mb->override_methods) {
11330                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
11331                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
11332
11333                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
11334                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
11335
11336                                         g_assert (mb->mhandle);
11337
11338                                         onum ++;
11339                                 }
11340                         }
11341                 }
11342         }
11343
11344         *num_overrides = onum;
11345 }
11346
11347 static void
11348 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
11349 {
11350         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11351         MonoReflectionFieldBuilder *fb;
11352         MonoClassField *field;
11353         MonoImage *image = klass->image;
11354         const char *p, *p2;
11355         int i;
11356         guint32 len, idx, real_size = 0;
11357
11358         klass->field.count = tb->num_fields;
11359         klass->field.first = 0;
11360
11361         mono_error_init (error);
11362
11363         if (tb->class_size) {
11364                 if ((tb->packing_size & 0xffffff00) != 0) {
11365                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
11366                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
11367                         return;
11368                 }
11369                 klass->packing_size = tb->packing_size;
11370                 real_size = klass->instance_size + tb->class_size;
11371         }
11372
11373         if (!klass->field.count) {
11374                 klass->instance_size = MAX (klass->instance_size, real_size);
11375                 return;
11376         }
11377         
11378         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
11379         mono_class_alloc_ext (klass);
11380         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
11381         /*
11382         This is, guess what, a hack.
11383         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
11384         On the static path no field class is resolved, only types are built. This is the right thing to do
11385         but we suck.
11386         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
11387         */
11388         klass->size_inited = 1;
11389
11390         for (i = 0; i < klass->field.count; ++i) {
11391                 MonoArray *rva_data;
11392                 fb = mono_array_get (tb->fields, gpointer, i);
11393                 field = &klass->fields [i];
11394                 field->name = mono_string_to_utf8_image (image, fb->name, error);
11395                 if (!mono_error_ok (error))
11396                         return;
11397                 if (fb->attrs) {
11398                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11399                         field->type->attrs = fb->attrs;
11400                 } else {
11401                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11402                 }
11403
11404                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
11405                         char *base = mono_array_addr (rva_data, char, 0);
11406                         size_t size = mono_array_length (rva_data);
11407                         char *data = mono_image_alloc (klass->image, size);
11408                         memcpy (data, base, size);
11409                         klass->ext->field_def_values [i].data = data;
11410                 }
11411                 if (fb->offset != -1)
11412                         field->offset = fb->offset;
11413                 field->parent = klass;
11414                 fb->handle = field;
11415                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
11416
11417                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
11418                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
11419                 }
11420                 if (fb->def_value) {
11421                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11422                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
11423                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
11424                         /* Copy the data from the blob since it might get realloc-ed */
11425                         p = assembly->blob.data + idx;
11426                         len = mono_metadata_decode_blob_size (p, &p2);
11427                         len += p2 - p;
11428                         klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
11429                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11430                 }
11431         }
11432
11433         klass->instance_size = MAX (klass->instance_size, real_size);
11434         mono_class_layout_fields (klass);
11435 }
11436
11437 static void
11438 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11439 {
11440         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11441         MonoReflectionPropertyBuilder *pb;
11442         MonoImage *image = klass->image;
11443         MonoProperty *properties;
11444         int i;
11445
11446         mono_error_init (error);
11447
11448         if (!klass->ext)
11449                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11450
11451         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11452         klass->ext->property.first = 0;
11453
11454         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11455         klass->ext->properties = properties;
11456         for (i = 0; i < klass->ext->property.count; ++i) {
11457                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11458                 properties [i].parent = klass;
11459                 properties [i].attrs = pb->attrs;
11460                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11461                 if (!mono_error_ok (error))
11462                         return;
11463                 if (pb->get_method)
11464                         properties [i].get = pb->get_method->mhandle;
11465                 if (pb->set_method)
11466                         properties [i].set = pb->set_method->mhandle;
11467
11468                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11469                 if (pb->def_value) {
11470                         guint32 len, idx;
11471                         const char *p, *p2;
11472                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11473                         if (!klass->ext->prop_def_values)
11474                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11475                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11476                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11477                         /* Copy the data from the blob since it might get realloc-ed */
11478                         p = assembly->blob.data + idx;
11479                         len = mono_metadata_decode_blob_size (p, &p2);
11480                         len += p2 - p;
11481                         klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11482                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11483                 }
11484         }
11485 }
11486
11487 MonoReflectionEvent *
11488 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11489 {
11490         MonoEvent *event = g_new0 (MonoEvent, 1);
11491         MonoClass *klass;
11492
11493         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11494
11495         event->parent = klass;
11496         event->attrs = eb->attrs;
11497         event->name = mono_string_to_utf8 (eb->name);
11498         if (eb->add_method)
11499                 event->add = eb->add_method->mhandle;
11500         if (eb->remove_method)
11501                 event->remove = eb->remove_method->mhandle;
11502         if (eb->raise_method)
11503                 event->raise = eb->raise_method->mhandle;
11504
11505 #ifndef MONO_SMALL_CONFIG
11506         if (eb->other_methods) {
11507                 int j;
11508                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11509                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11510                         MonoReflectionMethodBuilder *mb = 
11511                                 mono_array_get (eb->other_methods,
11512                                                 MonoReflectionMethodBuilder*, j);
11513                         event->other [j] = mb->mhandle;
11514                 }
11515         }
11516 #endif
11517
11518         return mono_event_get_object (mono_object_domain (tb), klass, event);
11519 }
11520
11521 static void
11522 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11523 {
11524         MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11525         MonoReflectionEventBuilder *eb;
11526         MonoImage *image = klass->image;
11527         MonoEvent *events;
11528         int i;
11529
11530         mono_error_init (error);
11531
11532         if (!klass->ext)
11533                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11534
11535         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11536         klass->ext->event.first = 0;
11537
11538         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11539         klass->ext->events = events;
11540         for (i = 0; i < klass->ext->event.count; ++i) {
11541                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11542                 events [i].parent = klass;
11543                 events [i].attrs = eb->attrs;
11544                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11545                 if (!mono_error_ok (error))
11546                         return;
11547                 if (eb->add_method)
11548                         events [i].add = eb->add_method->mhandle;
11549                 if (eb->remove_method)
11550                         events [i].remove = eb->remove_method->mhandle;
11551                 if (eb->raise_method)
11552                         events [i].raise = eb->raise_method->mhandle;
11553
11554 #ifndef MONO_SMALL_CONFIG
11555                 if (eb->other_methods) {
11556                         int j;
11557                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11558                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11559                                 MonoReflectionMethodBuilder *mb = 
11560                                         mono_array_get (eb->other_methods,
11561                                                                         MonoReflectionMethodBuilder*, j);
11562                                 events [i].other [j] = mb->mhandle;
11563                         }
11564                 }
11565 #endif
11566                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11567         }
11568 }
11569
11570 static gboolean
11571 remove_instantiations_of_and_ensure_contents (gpointer key,
11572                                                   gpointer value,
11573                                                   gpointer user_data)
11574 {
11575         MonoType *type = (MonoType*)key;
11576         MonoClass *klass = (MonoClass*)user_data;
11577
11578         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11579                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11580                 return TRUE;
11581         } else
11582                 return FALSE;
11583 }
11584
11585 static void
11586 check_array_for_usertypes (MonoArray *arr)
11587 {
11588         int i;
11589
11590         if (!arr)
11591                 return;
11592
11593         for (i = 0; i < mono_array_length (arr); ++i)
11594                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11595 }
11596
11597 MonoReflectionType*
11598 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11599 {
11600         MonoError error;
11601         MonoClass *klass;
11602         MonoDomain* domain;
11603         MonoReflectionType* res;
11604         int i, j;
11605
11606         domain = mono_object_domain (tb);
11607         klass = mono_class_from_mono_type (tb->type.type);
11608
11609         /*
11610          * Check for user defined Type subclasses.
11611          */
11612         RESOLVE_TYPE (tb->parent);
11613         check_array_for_usertypes (tb->interfaces);
11614         if (tb->fields) {
11615                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11616                         MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11617                         if (fb) {
11618                                 RESOLVE_TYPE (fb->type);
11619                                 check_array_for_usertypes (fb->modreq);
11620                                 check_array_for_usertypes (fb->modopt);
11621                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11622                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11623                         }
11624                 }
11625         }
11626         if (tb->methods) {
11627                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11628                         MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11629                         if (mb) {
11630                                 RESOLVE_TYPE (mb->rtype);
11631                                 check_array_for_usertypes (mb->return_modreq);
11632                                 check_array_for_usertypes (mb->return_modopt);
11633                                 check_array_for_usertypes (mb->parameters);
11634                                 if (mb->param_modreq)
11635                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11636                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11637                                 if (mb->param_modopt)
11638                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11639                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11640                         }
11641                 }
11642         }
11643         if (tb->ctors) {
11644                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11645                         MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11646                         if (mb) {
11647                                 check_array_for_usertypes (mb->parameters);
11648                                 if (mb->param_modreq)
11649                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11650                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11651                                 if (mb->param_modopt)
11652                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11653                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11654                         }
11655                 }
11656         }
11657
11658         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11659
11660         /* 
11661          * we need to lock the domain because the lock will be taken inside
11662          * So, we need to keep the locking order correct.
11663          */
11664         mono_loader_lock ();
11665         mono_domain_lock (domain);
11666         if (klass->wastypebuilder) {
11667                 mono_domain_unlock (domain);
11668                 mono_loader_unlock ();
11669                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11670         }
11671         /*
11672          * Fields to set in klass:
11673          * the various flags: delegate/unicode/contextbound etc.
11674          */
11675         klass->flags = tb->attrs;
11676         klass->has_cctor = 1;
11677         klass->has_finalize = 1;
11678         klass->has_finalize_inited = 1;
11679
11680         mono_class_setup_parent (klass, klass->parent);
11681         /* fool mono_class_setup_supertypes */
11682         klass->supertypes = NULL;
11683         mono_class_setup_supertypes (klass);
11684         mono_class_setup_mono_type (klass);
11685
11686 #if 0
11687         if (!((MonoDynamicImage*)klass->image)->run) {
11688                 if (klass->generic_container) {
11689                         /* FIXME: The code below can't handle generic classes */
11690                         klass->wastypebuilder = TRUE;
11691                         mono_loader_unlock ();
11692                         mono_domain_unlock (domain);
11693                         return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11694                 }
11695         }
11696 #endif
11697
11698         /* enums are done right away */
11699         if (!klass->enumtype)
11700                 ensure_runtime_vtable (klass);
11701
11702         if (tb->subtypes) {
11703                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11704                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11705                         mono_class_alloc_ext (klass);
11706                         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)));
11707                 }
11708         }
11709
11710         klass->nested_classes_inited = TRUE;
11711
11712         /* fields and object layout */
11713         if (klass->parent) {
11714                 if (!klass->parent->size_inited)
11715                         mono_class_init (klass->parent);
11716                 klass->instance_size = klass->parent->instance_size;
11717                 klass->sizes.class_size = 0;
11718                 klass->min_align = klass->parent->min_align;
11719                 /* if the type has no fields we won't call the field_setup
11720                  * routine which sets up klass->has_references.
11721                  */
11722                 klass->has_references |= klass->parent->has_references;
11723         } else {
11724                 klass->instance_size = sizeof (MonoObject);
11725                 klass->min_align = 1;
11726         }
11727
11728         /* FIXME: handle packing_size and instance_size */
11729         typebuilder_setup_fields (klass, &error);
11730         if (!mono_error_ok (&error))
11731                 goto failure;
11732         typebuilder_setup_properties (klass, &error);
11733         if (!mono_error_ok (&error))
11734                 goto failure;
11735
11736         typebuilder_setup_events (klass, &error);
11737         if (!mono_error_ok (&error))
11738                 goto failure;
11739
11740         klass->wastypebuilder = TRUE;
11741
11742         /* 
11743          * If we are a generic TypeBuilder, there might be instantiations in the type cache
11744          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
11745          * we want to return normal System.MonoType objects, so clear these out from the cache.
11746          *
11747          * Together with this we must ensure the contents of all instances to match the created type.
11748          */
11749         if (domain->type_hash && klass->generic_container)
11750                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11751
11752         mono_domain_unlock (domain);
11753         mono_loader_unlock ();
11754
11755         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11756                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11757                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11758         }
11759
11760         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11761         g_assert (res != (MonoReflectionType*)tb);
11762
11763         return res;
11764
11765 failure:
11766         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11767         klass->wastypebuilder = TRUE;
11768         mono_domain_unlock (domain);
11769         mono_loader_unlock ();
11770         mono_error_raise_exception (&error);
11771         return NULL;
11772 }
11773
11774 void
11775 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11776 {
11777         MonoGenericParamFull *param;
11778         MonoImage *image;
11779         MonoClass *pklass;
11780         MonoError error;
11781
11782         image = &gparam->tbuilder->module->dynamic_image->image;
11783
11784         param = mono_image_new0 (image, MonoGenericParamFull, 1);
11785
11786         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11787         g_assert (mono_error_ok (&error));
11788         param->param.num = gparam->index;
11789
11790         if (gparam->mbuilder) {
11791                 if (!gparam->mbuilder->generic_container) {
11792                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11793                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11794                         gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11795                         gparam->mbuilder->generic_container->is_method = TRUE;
11796                         /* 
11797                          * Cannot set owner.method, since the MonoMethod is not created yet.
11798                          * Set the image field instead, so type_in_image () works.
11799                          */
11800                         gparam->mbuilder->generic_container->image = klass->image;
11801                 }
11802                 param->param.owner = gparam->mbuilder->generic_container;
11803         } else if (gparam->tbuilder) {
11804                 if (!gparam->tbuilder->generic_container) {
11805                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11806                         gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11807                         gparam->tbuilder->generic_container->owner.klass = klass;
11808                 }
11809                 param->param.owner = gparam->tbuilder->generic_container;
11810         }
11811
11812         pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11813
11814         gparam->type.type = &pklass->byval_arg;
11815
11816         mono_class_set_ref_info (pklass, gparam);
11817         mono_image_append_class_to_reflection_info_set (pklass);
11818 }
11819
11820 MonoArray *
11821 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11822 {
11823         MonoReflectionModuleBuilder *module = sig->module;
11824         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11825         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11826         guint32 buflen, i;
11827         MonoArray *result;
11828         SigBuffer buf;
11829
11830         check_array_for_usertypes (sig->arguments);
11831
11832         sigbuffer_init (&buf, 32);
11833
11834         sigbuffer_add_value (&buf, 0x07);
11835         sigbuffer_add_value (&buf, na);
11836         if (assembly != NULL){
11837                 for (i = 0; i < na; ++i) {
11838                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11839                         encode_reflection_type (assembly, type, &buf);
11840                 }
11841         }
11842
11843         buflen = buf.p - buf.buf;
11844         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11845         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11846         sigbuffer_free (&buf);
11847
11848         return result;
11849 }
11850
11851 MonoArray *
11852 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11853 {
11854         MonoDynamicImage *assembly = sig->module->dynamic_image;
11855         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11856         guint32 buflen, i;
11857         MonoArray *result;
11858         SigBuffer buf;
11859
11860         check_array_for_usertypes (sig->arguments);
11861
11862         sigbuffer_init (&buf, 32);
11863
11864         sigbuffer_add_value (&buf, 0x06);
11865         for (i = 0; i < na; ++i) {
11866                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11867                 encode_reflection_type (assembly, type, &buf);
11868         }
11869
11870         buflen = buf.p - buf.buf;
11871         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11872         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11873         sigbuffer_free (&buf);
11874
11875         return result;
11876 }
11877
11878 typedef struct {
11879         MonoMethod *handle;
11880         MonoDomain *domain;
11881 } DynamicMethodReleaseData;
11882
11883 /*
11884  * The runtime automatically clean up those after finalization.
11885 */      
11886 static MonoReferenceQueue *dynamic_method_queue;
11887
11888 static void
11889 free_dynamic_method (void *dynamic_method)
11890 {
11891         DynamicMethodReleaseData *data = dynamic_method;
11892         MonoDomain *domain = data->domain;
11893         MonoMethod *method = data->handle;
11894         guint32 dis_link;
11895
11896         mono_domain_lock (domain);
11897         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
11898         g_hash_table_remove (domain->method_to_dyn_method, method);
11899         mono_domain_unlock (domain);
11900         g_assert (dis_link);
11901         mono_gchandle_free (dis_link);
11902
11903         mono_runtime_free_method (domain, method);
11904         g_free (data);
11905 }
11906
11907 void 
11908 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11909 {
11910         MonoReferenceQueue *queue;
11911         MonoMethod *handle;
11912         DynamicMethodReleaseData *release_data;
11913         ReflectionMethodBuilder rmb;
11914         MonoMethodSignature *sig;
11915         MonoClass *klass;
11916         MonoDomain *domain;
11917         GSList *l;
11918         int i;
11919
11920         if (mono_runtime_is_shutting_down ())
11921                 mono_raise_exception (mono_get_exception_invalid_operation (""));
11922
11923         if (!(queue = dynamic_method_queue)) {
11924                 mono_loader_lock ();
11925                 if (!(queue = dynamic_method_queue))
11926                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11927                 mono_loader_unlock ();
11928         }
11929
11930         sig = dynamic_method_to_signature (mb);
11931
11932         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11933
11934         /*
11935          * Resolve references.
11936          */
11937         /* 
11938          * Every second entry in the refs array is reserved for storing handle_class,
11939          * which is needed by the ldtoken implementation in the JIT.
11940          */
11941         rmb.nrefs = mb->nrefs;
11942         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11943         for (i = 0; i < mb->nrefs; i += 2) {
11944                 MonoClass *handle_class;
11945                 gpointer ref;
11946                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11947
11948                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11949                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11950                         /*
11951                          * The referenced DynamicMethod should already be created by the managed
11952                          * code, except in the case of circular references. In that case, we store
11953                          * method in the refs array, and fix it up later when the referenced 
11954                          * DynamicMethod is created.
11955                          */
11956                         if (method->mhandle) {
11957                                 ref = method->mhandle;
11958                         } else {
11959                                 /* FIXME: GC object stored in unmanaged memory */
11960                                 ref = method;
11961
11962                                 /* FIXME: GC object stored in unmanaged memory */
11963                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
11964                         }
11965                         handle_class = mono_defaults.methodhandle_class;
11966                 } else {
11967                         MonoException *ex = NULL;
11968                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11969                         if (!ref)
11970                                 ex = mono_get_exception_type_load (NULL, NULL);
11971                         else if (mono_security_core_clr_enabled ())
11972                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11973
11974                         if (ex) {
11975                                 g_free (rmb.refs);
11976                                 mono_raise_exception (ex);
11977                                 return;
11978                         }
11979                 }
11980
11981                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11982                 rmb.refs [i + 1] = handle_class;
11983         }               
11984
11985         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11986
11987         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11988         release_data = g_new (DynamicMethodReleaseData, 1);
11989         release_data->handle = handle;
11990         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11991         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11992                 g_free (release_data);
11993
11994         /* Fix up refs entries pointing at us */
11995         for (l = mb->referenced_by; l; l = l->next) {
11996                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11997                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11998                 gpointer *data;
11999                 
12000                 g_assert (method->mhandle);
12001
12002                 data = (gpointer*)wrapper->method_data;
12003                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12004                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12005                                 data [i + 1] = mb->mhandle;
12006                 }
12007         }
12008         g_slist_free (mb->referenced_by);
12009
12010         g_free (rmb.refs);
12011
12012         /* ilgen is no longer needed */
12013         mb->ilgen = NULL;
12014
12015         domain = mono_domain_get ();
12016         mono_domain_lock (domain);
12017         if (!domain->method_to_dyn_method)
12018                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12019         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12020         mono_domain_unlock (domain);
12021 }
12022
12023 #endif /* DISABLE_REFLECTION_EMIT */
12024
12025 /**
12026  * 
12027  * mono_reflection_is_valid_dynamic_token:
12028  * 
12029  * Returns TRUE if token is valid.
12030  * 
12031  */
12032 gboolean
12033 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12034 {
12035         return lookup_dyn_token (image, token) != NULL;
12036 }
12037
12038 MonoMethodSignature *
12039 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12040 {
12041         MonoMethodSignature *sig;
12042         g_assert (image_is_dynamic (image));
12043
12044         mono_error_init (error);
12045
12046         sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12047         if (sig)
12048                 return sig;
12049
12050         return mono_method_signature_checked (method, error);
12051 }
12052
12053 #ifndef DISABLE_REFLECTION_EMIT
12054
12055 /**
12056  * mono_reflection_lookup_dynamic_token:
12057  *
12058  * Finish the Builder object pointed to by TOKEN and return the corresponding
12059  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12060  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12061  * mapping table.
12062  *
12063  * LOCKING: Take the loader lock
12064  */
12065 gpointer
12066 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12067 {
12068         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12069         MonoObject *obj;
12070         MonoClass *klass;
12071
12072         obj = lookup_dyn_token (assembly, token);
12073         if (!obj) {
12074                 if (valid_token)
12075                         g_error ("Could not find required dynamic token 0x%08x", token);
12076                 else
12077                         return NULL;
12078         }
12079
12080         if (!handle_class)
12081                 handle_class = &klass;
12082         return resolve_object (image, obj, handle_class, context);
12083 }
12084
12085 /*
12086  * ensure_complete_type:
12087  *
12088  *   Ensure that KLASS is completed if it is a dynamic type, or references
12089  * dynamic types.
12090  */
12091 static void
12092 ensure_complete_type (MonoClass *klass)
12093 {
12094         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12095                 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
12096
12097                 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12098
12099                 // Asserting here could break a lot of code
12100                 //g_assert (klass->wastypebuilder);
12101         }
12102
12103         if (klass->generic_class) {
12104                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12105                 int i;
12106
12107                 for (i = 0; i < inst->type_argc; ++i) {
12108                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12109                 }
12110         }
12111 }
12112
12113 static gpointer
12114 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12115 {
12116         gpointer result = NULL;
12117
12118         if (strcmp (obj->vtable->klass->name, "String") == 0) {
12119                 result = mono_string_intern ((MonoString*)obj);
12120                 *handle_class = mono_defaults.string_class;
12121                 g_assert (result);
12122         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12123                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12124                 MonoClass *mc = mono_class_from_mono_type (type);
12125                 if (!mono_class_init (mc))
12126                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
12127
12128                 if (context) {
12129                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12130                         result = mono_class_from_mono_type (inflated);
12131                         mono_metadata_free_type (inflated);
12132                 } else {
12133                         result = mono_class_from_mono_type (type);
12134                 }
12135                 *handle_class = mono_defaults.typehandle_class;
12136                 g_assert (result);
12137         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12138                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12139                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12140                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12141                 result = ((MonoReflectionMethod*)obj)->method;
12142                 if (context) {
12143                         MonoError error;
12144                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12145                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12146                 }
12147                 *handle_class = mono_defaults.methodhandle_class;
12148                 g_assert (result);
12149         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12150                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12151                 result = mb->mhandle;
12152                 if (!result) {
12153                         /* Type is not yet created */
12154                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12155
12156                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12157
12158                         /*
12159                          * Hopefully this has been filled in by calling CreateType() on the
12160                          * TypeBuilder.
12161                          */
12162                         /*
12163                          * TODO: This won't work if the application finishes another 
12164                          * TypeBuilder instance instead of this one.
12165                          */
12166                         result = mb->mhandle;
12167                 }
12168                 if (context) {
12169                         MonoError error;
12170                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12171                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12172                 }
12173                 *handle_class = mono_defaults.methodhandle_class;
12174         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12175                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12176
12177                 result = cb->mhandle;
12178                 if (!result) {
12179                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12180
12181                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12182                         result = cb->mhandle;
12183                 }
12184                 if (context) {
12185                         MonoError error;
12186                         result = mono_class_inflate_generic_method_checked (result, context, &error);
12187                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12188                 }
12189                 *handle_class = mono_defaults.methodhandle_class;
12190         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12191                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12192
12193                 ensure_complete_type (field->parent);
12194                 if (context) {
12195                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12196                         MonoClass *class = mono_class_from_mono_type (inflated);
12197                         MonoClassField *inflated_field;
12198                         gpointer iter = NULL;
12199                         mono_metadata_free_type (inflated);
12200                         while ((inflated_field = mono_class_get_fields (class, &iter))) {
12201                                 if (!strcmp (field->name, inflated_field->name))
12202                                         break;
12203                         }
12204                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12205                         result = inflated_field;
12206                 } else {
12207                         result = field;
12208                 }
12209                 *handle_class = mono_defaults.fieldhandle_class;
12210                 g_assert (result);
12211         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
12212                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
12213                 result = fb->handle;
12214
12215                 if (!result) {
12216                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
12217
12218                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12219                         result = fb->handle;
12220                 }
12221
12222                 if (fb->handle && fb->handle->parent->generic_container) {
12223                         MonoClass *klass = fb->handle->parent;
12224                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
12225                         MonoClass *inflated = mono_class_from_mono_type (type);
12226
12227                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
12228                         g_assert (result);
12229                         mono_metadata_free_type (type);
12230                 }
12231                 *handle_class = mono_defaults.fieldhandle_class;
12232         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
12233                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
12234                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
12235                 MonoClass *klass;
12236
12237                 klass = type->data.klass;
12238                 if (klass->wastypebuilder) {
12239                         /* Already created */
12240                         result = klass;
12241                 }
12242                 else {
12243                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
12244                         result = type->data.klass;
12245                         g_assert (result);
12246                 }
12247                 *handle_class = mono_defaults.typehandle_class;
12248         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
12249                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
12250                 MonoMethodSignature *sig;
12251                 int nargs, i;
12252
12253                 if (helper->arguments)
12254                         nargs = mono_array_length (helper->arguments);
12255                 else
12256                         nargs = 0;
12257
12258                 sig = mono_metadata_signature_alloc (image, nargs);
12259                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
12260                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
12261
12262                 if (helper->unmanaged_call_conv) { /* unmanaged */
12263                         sig->call_convention = helper->unmanaged_call_conv - 1;
12264                         sig->pinvoke = TRUE;
12265                 } else if (helper->call_conv & 0x02) {
12266                         sig->call_convention = MONO_CALL_VARARG;
12267                 } else {
12268                         sig->call_convention = MONO_CALL_DEFAULT;
12269                 }
12270
12271                 sig->param_count = nargs;
12272                 /* TODO: Copy type ? */
12273                 sig->ret = helper->return_type->type;
12274                 for (i = 0; i < nargs; ++i)
12275                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
12276
12277                 result = sig;
12278                 *handle_class = NULL;
12279         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12280                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12281                 /* Already created by the managed code */
12282                 g_assert (method->mhandle);
12283                 result = method->mhandle;
12284                 *handle_class = mono_defaults.methodhandle_class;
12285         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
12286                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12287                 type = mono_class_inflate_generic_type (type, context);
12288                 result = mono_class_from_mono_type (type);
12289                 *handle_class = mono_defaults.typehandle_class;
12290                 g_assert (result);
12291                 mono_metadata_free_type (type);
12292         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
12293                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12294                 type = mono_class_inflate_generic_type (type, context);
12295                 result = mono_class_from_mono_type (type);
12296                 *handle_class = mono_defaults.typehandle_class;
12297                 g_assert (result);
12298                 mono_metadata_free_type (type);
12299         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
12300                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
12301                 MonoClass *inflated;
12302                 MonoType *type;
12303                 MonoClassField *field;
12304
12305                 if (is_sre_field_builder (mono_object_class (f->fb)))
12306                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
12307                 else if (is_sr_mono_field (mono_object_class (f->fb)))
12308                         field = ((MonoReflectionField*)f->fb)->field;
12309                 else
12310                         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)));
12311
12312                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
12313                 inflated = mono_class_from_mono_type (type);
12314
12315                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
12316                 ensure_complete_type (field->parent);
12317                 g_assert (result);
12318                 mono_metadata_free_type (type);
12319                 *handle_class = mono_defaults.fieldhandle_class;
12320         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
12321                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
12322                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
12323                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
12324                 MonoMethod *method;
12325
12326                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
12327                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
12328                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
12329                         method = ((MonoReflectionMethod *)c->cb)->method;
12330                 else
12331                         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)));
12332
12333                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
12334                 *handle_class = mono_defaults.methodhandle_class;
12335                 mono_metadata_free_type (type);
12336         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
12337                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
12338                 if (m->method_args) {
12339                         result = mono_reflection_method_on_tb_inst_get_handle (m);
12340                         if (context) {
12341                                 MonoError error;
12342                                 result = mono_class_inflate_generic_method_checked (result, context, &error);
12343                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12344                         }
12345                 } else {
12346                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
12347                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12348                         MonoMethod *method;
12349
12350                         if (is_sre_method_builder (mono_object_class (m->mb)))
12351                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12352                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12353                                 method = ((MonoReflectionMethod *)m->mb)->method;
12354                         else
12355                                 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)));
12356
12357                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
12358                         mono_metadata_free_type (type);
12359                 }
12360                 *handle_class = mono_defaults.methodhandle_class;
12361         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
12362                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
12363                 MonoType *mtype;
12364                 MonoClass *klass;
12365                 MonoMethod *method;
12366                 gpointer iter;
12367                 char *name;
12368
12369                 mtype = mono_reflection_type_get_handle (m->parent);
12370                 klass = mono_class_from_mono_type (mtype);
12371
12372                 /* Find the method */
12373
12374                 name = mono_string_to_utf8 (m->name);
12375                 iter = NULL;
12376                 while ((method = mono_class_get_methods (klass, &iter))) {
12377                         if (!strcmp (method->name, name))
12378                                 break;
12379                 }
12380                 g_free (name);
12381
12382                 // FIXME:
12383                 g_assert (method);
12384                 // FIXME: Check parameters/return value etc. match
12385
12386                 result = method;
12387                 *handle_class = mono_defaults.methodhandle_class;
12388         } else if (is_sre_array (mono_object_get_class(obj)) ||
12389                                 is_sre_byref (mono_object_get_class(obj)) ||
12390                                 is_sre_pointer (mono_object_get_class(obj))) {
12391                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
12392                 MonoType *type = mono_reflection_type_get_handle (ref_type);
12393
12394                 if (context) {
12395                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12396                         result = mono_class_from_mono_type (inflated);
12397                         mono_metadata_free_type (inflated);
12398                 } else {
12399                         result = mono_class_from_mono_type (type);
12400                 }
12401                 *handle_class = mono_defaults.typehandle_class;
12402         } else {
12403                 g_print ("%s\n", obj->vtable->klass->name);
12404                 g_assert_not_reached ();
12405         }
12406         return result;
12407 }
12408
12409 #else /* DISABLE_REFLECTION_EMIT */
12410
12411 MonoArray*
12412 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
12413 {
12414         g_assert_not_reached ();
12415         return NULL;
12416 }
12417
12418 void
12419 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
12420 {
12421         g_assert_not_reached ();
12422 }
12423
12424 void
12425 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
12426 {
12427         g_assert_not_reached ();
12428 }
12429
12430 void
12431 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
12432 {
12433         g_assert_not_reached ();
12434 }
12435
12436 void
12437 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
12438 {
12439         g_assert_not_reached ();
12440 }
12441
12442 void
12443 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
12444 {
12445         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
12446 }
12447
12448 void
12449 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
12450 {
12451         g_assert_not_reached ();
12452 }
12453
12454 void
12455 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
12456 {
12457         g_assert_not_reached ();
12458 }
12459
12460 MonoReflectionModule *
12461 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
12462 {
12463         g_assert_not_reached ();
12464         return NULL;
12465 }
12466
12467 guint32
12468 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12469 {
12470         g_assert_not_reached ();
12471         return 0;
12472 }
12473
12474 guint32
12475 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12476 {
12477         g_assert_not_reached ();
12478         return 0;
12479 }
12480
12481 guint32
12482 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
12483                                                  gboolean create_open_instance, gboolean register_token)
12484 {
12485         g_assert_not_reached ();
12486         return 0;
12487 }
12488
12489 void
12490 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12491 {
12492 }
12493
12494 void
12495 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12496 {
12497         g_assert_not_reached ();
12498 }
12499
12500 void
12501 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12502 {
12503         *overrides = NULL;
12504         *num_overrides = 0;
12505 }
12506
12507 MonoReflectionEvent *
12508 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12509 {
12510         g_assert_not_reached ();
12511         return NULL;
12512 }
12513
12514 MonoReflectionType*
12515 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12516 {
12517         g_assert_not_reached ();
12518         return NULL;
12519 }
12520
12521 void
12522 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12523 {
12524         g_assert_not_reached ();
12525 }
12526
12527 MonoArray *
12528 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12529 {
12530         g_assert_not_reached ();
12531         return NULL;
12532 }
12533
12534 MonoArray *
12535 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12536 {
12537         g_assert_not_reached ();
12538         return NULL;
12539 }
12540
12541 void 
12542 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12543 {
12544 }
12545
12546 gpointer
12547 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12548 {
12549         return NULL;
12550 }
12551
12552 MonoType*
12553 mono_reflection_type_get_handle (MonoReflectionType* ref)
12554 {
12555         if (!ref)
12556                 return NULL;
12557         return ref->type;
12558 }
12559
12560 void
12561 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12562 {
12563         g_assert_not_reached ();
12564 }
12565
12566 #endif /* DISABLE_REFLECTION_EMIT */
12567
12568 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12569 const static guint32 declsec_flags_map[] = {
12570         0x00000000,                                     /* empty */
12571         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
12572         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
12573         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
12574         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
12575         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
12576         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
12577         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
12578         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
12579         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
12580         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
12581         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
12582         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
12583         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
12584         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
12585         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
12586         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
12587         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
12588         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
12589 };
12590
12591 /*
12592  * Returns flags that includes all available security action associated to the handle.
12593  * @token: metadata token (either for a class or a method)
12594  * @image: image where resides the metadata.
12595  */
12596 static guint32
12597 mono_declsec_get_flags (MonoImage *image, guint32 token)
12598 {
12599         int index = mono_metadata_declsec_from_index (image, token);
12600         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12601         guint32 result = 0;
12602         guint32 action;
12603         int i;
12604
12605         /* HasSecurity can be present for other, not specially encoded, attributes,
12606            e.g. SuppressUnmanagedCodeSecurityAttribute */
12607         if (index < 0)
12608                 return 0;
12609
12610         for (i = index; i < t->rows; i++) {
12611                 guint32 cols [MONO_DECL_SECURITY_SIZE];
12612
12613                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12614                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12615                         break;
12616
12617                 action = cols [MONO_DECL_SECURITY_ACTION];
12618                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12619                         result |= declsec_flags_map [action];
12620                 } else {
12621                         g_assert_not_reached ();
12622                 }
12623         }
12624         return result;
12625 }
12626
12627 /*
12628  * Get the security actions (in the form of flags) associated with the specified method.
12629  *
12630  * @method: The method for which we want the declarative security flags.
12631  * Return the declarative security flags for the method (only).
12632  *
12633  * Note: To keep MonoMethod size down we do not cache the declarative security flags
12634  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
12635  */
12636 guint32
12637 mono_declsec_flags_from_method (MonoMethod *method)
12638 {
12639         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12640                 /* FIXME: No cache (for the moment) */
12641                 guint32 idx = mono_method_get_index (method);
12642                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12643                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12644                 return mono_declsec_get_flags (method->klass->image, idx);
12645         }
12646         return 0;
12647 }
12648
12649 /*
12650  * Get the security actions (in the form of flags) associated with the specified class.
12651  *
12652  * @klass: The class for which we want the declarative security flags.
12653  * Return the declarative security flags for the class.
12654  *
12655  * Note: We cache the flags inside the MonoClass structure as this will get 
12656  *       called very often (at least for each method).
12657  */
12658 guint32
12659 mono_declsec_flags_from_class (MonoClass *klass)
12660 {
12661         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12662                 if (!klass->ext || !klass->ext->declsec_flags) {
12663                         guint32 idx;
12664
12665                         idx = mono_metadata_token_index (klass->type_token);
12666                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12667                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12668                         mono_loader_lock ();
12669                         mono_class_alloc_ext (klass);
12670                         mono_loader_unlock ();
12671                         /* we cache the flags on classes */
12672                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12673                 }
12674                 return klass->ext->declsec_flags;
12675         }
12676         return 0;
12677 }
12678
12679 /*
12680  * Get the security actions (in the form of flags) associated with the specified assembly.
12681  *
12682  * @assembly: The assembly for which we want the declarative security flags.
12683  * Return the declarative security flags for the assembly.
12684  */
12685 guint32
12686 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12687 {
12688         guint32 idx = 1; /* there is only one assembly */
12689         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12690         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12691         return mono_declsec_get_flags (assembly->image, idx);
12692 }
12693
12694
12695 /*
12696  * Fill actions for the specific index (which may either be an encoded class token or
12697  * an encoded method token) from the metadata image.
12698  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12699  */
12700 static MonoBoolean
12701 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12702         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12703 {
12704         MonoBoolean result = FALSE;
12705         MonoTableInfo *t;
12706         guint32 cols [MONO_DECL_SECURITY_SIZE];
12707         int index = mono_metadata_declsec_from_index (image, token);
12708         int i;
12709
12710         t  = &image->tables [MONO_TABLE_DECLSECURITY];
12711         for (i = index; i < t->rows; i++) {
12712                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12713
12714                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12715                         return result;
12716
12717                 /* if present only replace (class) permissions with method permissions */
12718                 /* if empty accept either class or method permissions */
12719                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12720                         if (!actions->demand.blob) {
12721                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12722                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12723                                 actions->demand.blob = (char*) (blob + 2);
12724                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12725                                 result = TRUE;
12726                         }
12727                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12728                         if (!actions->noncasdemand.blob) {
12729                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12730                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12731                                 actions->noncasdemand.blob = (char*) (blob + 2);
12732                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12733                                 result = TRUE;
12734                         }
12735                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12736                         if (!actions->demandchoice.blob) {
12737                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12738                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12739                                 actions->demandchoice.blob = (char*) (blob + 2);
12740                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12741                                 result = TRUE;
12742                         }
12743                 }
12744         }
12745
12746         return result;
12747 }
12748
12749 static MonoBoolean
12750 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
12751         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12752 {
12753         guint32 idx = mono_metadata_token_index (klass->type_token);
12754         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12755         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12756         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12757 }
12758
12759 static MonoBoolean
12760 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
12761         guint32 id_std, guint32 id_noncas, guint32 id_choice)
12762 {
12763         guint32 idx = mono_method_get_index (method);
12764         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12765         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12766         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12767 }
12768
12769 /*
12770  * Collect all actions (that requires to generate code in mini) assigned for
12771  * the specified method.
12772  * Note: Don't use the content of actions if the function return FALSE.
12773  */
12774 MonoBoolean
12775 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12776 {
12777         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
12778                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12779         MonoBoolean result = FALSE;
12780         guint32 flags;
12781
12782         /* quick exit if no declarative security is present in the metadata */
12783         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12784                 return FALSE;
12785
12786         /* we want the original as the wrapper is "free" of the security informations */
12787         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12788                 method = mono_marshal_method_from_wrapper (method);
12789                 if (!method)
12790                         return FALSE;
12791         }
12792
12793         /* First we look for method-level attributes */
12794         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12795                 mono_class_init (method->klass);
12796                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12797
12798                 result = mono_declsec_get_method_demands_params (method, demands, 
12799                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12800         }
12801
12802         /* Here we use (or create) the class declarative cache to look for demands */
12803         flags = mono_declsec_flags_from_class (method->klass);
12804         if (flags & mask) {
12805                 if (!result) {
12806                         mono_class_init (method->klass);
12807                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
12808                 }
12809                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
12810                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12811         }
12812
12813         /* The boolean return value is used as a shortcut in case nothing needs to
12814            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12815         return result;
12816 }
12817
12818
12819 /*
12820  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12821  *
12822  * Note: Don't use the content of actions if the function return FALSE.
12823  */
12824 MonoBoolean
12825 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12826 {
12827         MonoBoolean result = FALSE;
12828         guint32 flags;
12829
12830         /* quick exit if no declarative security is present in the metadata */
12831         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12832                 return FALSE;
12833
12834         /* we want the original as the wrapper is "free" of the security informations */
12835         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12836                 method = mono_marshal_method_from_wrapper (method);
12837                 if (!method)
12838                         return FALSE;
12839         }
12840
12841         /* results are independant - zeroize both */
12842         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12843         memset (klass, 0, sizeof (MonoDeclSecurityActions));
12844
12845         /* First we look for method-level attributes */
12846         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12847                 mono_class_init (method->klass);
12848
12849                 result = mono_declsec_get_method_demands_params (method, cmethod, 
12850                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12851         }
12852
12853         /* Here we use (or create) the class declarative cache to look for demands */
12854         flags = mono_declsec_flags_from_class (method->klass);
12855         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12856                 mono_class_init (method->klass);
12857
12858                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
12859                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12860         }
12861
12862         return result;
12863 }
12864
12865 /*
12866  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12867  *
12868  * @klass       The inherited class - this is the class that provides the security check (attributes)
12869  * @demans      
12870  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12871  * 
12872  * Note: Don't use the content of actions if the function return FALSE.
12873  */
12874 MonoBoolean
12875 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12876 {
12877         MonoBoolean result = FALSE;
12878         guint32 flags;
12879
12880         /* quick exit if no declarative security is present in the metadata */
12881         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12882                 return FALSE;
12883
12884         /* Here we use (or create) the class declarative cache to look for demands */
12885         flags = mono_declsec_flags_from_class (klass);
12886         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12887                 mono_class_init (klass);
12888                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12889
12890                 result |= mono_declsec_get_class_demands_params (klass, demands, 
12891                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12892         }
12893
12894         return result;
12895 }
12896
12897 /*
12898  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12899  *
12900  * Note: Don't use the content of actions if the function return FALSE.
12901  */
12902 MonoBoolean
12903 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12904 {
12905         /* quick exit if no declarative security is present in the metadata */
12906         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12907                 return FALSE;
12908
12909         /* we want the original as the wrapper is "free" of the security informations */
12910         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12911                 method = mono_marshal_method_from_wrapper (method);
12912                 if (!method)
12913                         return FALSE;
12914         }
12915
12916         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12917                 mono_class_init (method->klass);
12918                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12919
12920                 return mono_declsec_get_method_demands_params (method, demands, 
12921                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12922         }
12923         return FALSE;
12924 }
12925
12926
12927 static MonoBoolean
12928 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12929 {
12930         guint32 cols [MONO_DECL_SECURITY_SIZE];
12931         MonoTableInfo *t;
12932         int i;
12933
12934         int index = mono_metadata_declsec_from_index (image, token);
12935         if (index == -1)
12936                 return FALSE;
12937
12938         t =  &image->tables [MONO_TABLE_DECLSECURITY];
12939         for (i = index; i < t->rows; i++) {
12940                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12941
12942                 /* shortcut - index are ordered */
12943                 if (token != cols [MONO_DECL_SECURITY_PARENT])
12944                         return FALSE;
12945
12946                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12947                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12948                         entry->blob = (char*) (metadata + 2);
12949                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12950                         return TRUE;
12951                 }
12952         }
12953
12954         return FALSE;
12955 }
12956
12957 MonoBoolean
12958 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12959 {
12960         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12961                 guint32 idx = mono_method_get_index (method);
12962                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12963                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12964                 return get_declsec_action (method->klass->image, idx, action, entry);
12965         }
12966         return FALSE;
12967 }
12968
12969 MonoBoolean
12970 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12971 {
12972         /* use cache */
12973         guint32 flags = mono_declsec_flags_from_class (klass);
12974         if (declsec_flags_map [action] & flags) {
12975                 guint32 idx = mono_metadata_token_index (klass->type_token);
12976                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12977                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12978                 return get_declsec_action (klass->image, idx, action, entry);
12979         }
12980         return FALSE;
12981 }
12982
12983 MonoBoolean
12984 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12985 {
12986         guint32 idx = 1; /* there is only one assembly */
12987         idx <<= MONO_HAS_DECL_SECURITY_BITS;
12988         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12989
12990         return get_declsec_action (assembly->image, idx, action, entry);
12991 }
12992
12993 gboolean
12994 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12995 {
12996         MonoObject *res, *exc;
12997         void *params [1];
12998         static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12999         static MonoMethod *method = NULL;
13000
13001         if (!System_Reflection_Emit_TypeBuilder) {
13002                 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
13003                 g_assert (System_Reflection_Emit_TypeBuilder);
13004         }
13005         if (method == NULL) {
13006                 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
13007                 g_assert (method);
13008         }
13009
13010         /* 
13011          * The result of mono_type_get_object () might be a System.MonoType but we
13012          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13013          */
13014         g_assert (mono_class_get_ref_info (klass));
13015         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13016
13017         params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
13018
13019         res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
13020         if (exc)
13021                 return FALSE;
13022         else
13023                 return *(MonoBoolean*)mono_object_unbox (res);
13024 }
13025
13026 /**
13027  * mono_reflection_type_get_type:
13028  * @reftype: the System.Type object
13029  *
13030  * Returns the MonoType* associated with the C# System.Type object @reftype.
13031  */
13032 MonoType*
13033 mono_reflection_type_get_type (MonoReflectionType *reftype)
13034 {
13035         g_assert (reftype);
13036
13037         return mono_reflection_type_get_handle (reftype);
13038 }
13039
13040 /**
13041  * mono_reflection_assembly_get_assembly:
13042  * @refassembly: the System.Reflection.Assembly object
13043  *
13044  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13045  */
13046 MonoAssembly*
13047 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13048 {
13049         g_assert (refassembly);
13050
13051         return refassembly->assembly;
13052 }
13053